在匿名函数内联中将 NaN 设置为零

setting NaNs to zero in an anonymous function inline

我使用匿名函数实现了分段函数,该函数也可以在向量或矩阵中求值:

 f = @(x) exp(((x-.25).*(x-.75)).^-1) .* (.25 < x & x < .75);

问题是在 0.250.75 处对其进行评估时,我们尝试对 Inf * 0 进行评估,结果为 NaN。我想将这些 NaN 值设置为零。我知道这可以使用文件中定义的函数轻松完成,但我想知道是否有一种解决方案可以让您内联执行此操作。 (可能定义其他匿名辅助函数。)

所以假设 x 是一个列向量,下面的解决方案可行,但不是很优雅:

deNaNify1 = @(x)x((2:2:end)-isnan(x(2,:)));
deNaNify = @(x)deNaNify1([zeros(size(x'));x'])

这个怎么样:

g = @(x) sum(cat(length(size(x))+1,x-1,~isnan(x)),length(size(x))+1,'omitnan');
x=1./(rand(100)>0.5);x=x.*0;x=x+10; %demo data with nan and 10
y=g(x); %now it has 0 and 10;

诀窍是使用 'omitnan' 求和。它对每个非 nan 值求和 1,对每个 nan 求和 0。它在求和中省略了 nan,因此每个 nan 都变为 0。通过预先从每个值中减去 1,它 returns 原始值。

当然

x(isnan(x))=0;

也可以,但不能在匿名函数中使用。

要摆脱 NaN,您可以利用 max 等函数忽略 NaN 的事实:

>> max(NaN, 0)
ans =
     0

这也适用于矢量化:

>> max([1 2 NaN 4], 0)
ans =
     1     2     0     4

您正在使用的数学函数是非负的。因此,如果 y 是由您的问题中定义的匿名函数产生的数组,则 max(y, NaN) 将保留 y 的数字条目不变,并将 NaN 转换为 0.

最后,将匿名函数修改为包含一个外部max(..., 0):

f = @(x) max(exp(((x-.25).*(x-.75)).^-1) .* (.25 < x & x < .75), 0);

这给出了,例如,

>> f([.2 .25 .4 .5 .6 .75 .8])
ans =
   1.0e-06 *
         0         0    0.0053    0.1125    0.0053         0         0

简而言之:对于以下实数,将 NaN 设置为零:

denanify = @(y) min(y,0)-min(-y,0)