矩阵中每个元素的条件函数

huangapple go评论62阅读模式
英文:

Conditional function for each element of a matrix

问题

我想要定义一个函数 y(x),如下所示:

如果 x >= 0:   y = x^(1/2)
如果 x < 0:    y = NaN

我已经尝试了下面的代码,显然不起作用。

y = @(x) (x>=0) * x.^(1/2) - NaN* (x<0); 
Test = y([-1,1,4,9])

我的期望是:

y([-1,1,4,9]) = [NaN, 1, 2, 3];

在我有限的理解中,arrayfun 可能会有帮助,但速度可能会很慢。请帮我找到一个解决方案。非常感谢。

编辑:正如Cris Luengo指出的那样,我在问题中不小心没有使用逐元素相乘 .*。请注意,即使使用 .*,我的方法仍然不起作用。

y = @(x) (x>=0) .* x^(1/2) - NaN.* (x<0); 
Test = y([-1,1,4,9])
英文:

I want to define a function y(x) as follows:

if x &gt;= 0:     y = x^(1/2)
if x&lt; 0:       y = NaN

I have tried below code, which clearly does not work.

y = @(x) (x&gt;=0) * x.^(1/2) - NaN* (x&lt;0); 
Test = y([-1,1,4,9])

My expectation is that:

y([-1,1,4,9]) = [NaN, 1, 2, 3];

In my limited understanding, arrayfun might help, but it would be very slow. Kindly help me a solution. Many thanks.

Edit. As pointed out by Cris Luengo, I did negligently not use wise-element .* in my question. Note that, even if using .*, my approach does not work.

y = @(x) (x&gt;=0) .* x^(1/2) - NaN.* (x&lt;0); 
Test = y([-1,1,4,9])

答案1

得分: 2

函数的目的是什么?如果在内联函数中实现if语句很困难,那么使用如下的关系运算符如何?

x = [-1, 1, 4, 9];

x(x>=0) = x(x>=0).^(1/2);
x(x<0) = NaN;

>> x

x =

   NaN     1     2     3
英文:

What is the purpose of having a function? If statement is hard to implement in an inline function. What about using relational operators like below?

x = [-1, 1, 4, 9];

x(x&gt;=0) = x(x&gt;=0).^(1/2);
x(x&lt;0) = NaN;

&gt;&gt; x

x =

   NaN     1     2     3

答案2

得分: 2

代码中的问题在于给定的代码中,NaN 乘以任何数都是 NaN。NaN 会通过设计在所有计算中传播;它是一个错误条件。

(代码的另一个问题是它计算了矩阵乘法和矩阵幂。应该使用元素级运算符 .*.^(x>=0) .* x.^(1/2)。)

通常,你可以在两行代码中实现你的目标:

y = x.^(1/2);
y(x<0) = NaN;

但对于这种特殊情况,我们可以通过将 x>=0 除以自身来创建一个在 x<0 时为 NaN 的值:(x>=0)./(x>=0) .* x.^(1/2)。除法的结果要么是 NaN,要么是 1,乘以 x 的平方根将得到 NaN 或 x 的平方根。

在这里,我发现另一个问题:如果 x 的任何元素为负数,x.^(1/2) 就是复数。因此,我们需要取其结果的实部:

y = @(x) (x>=0)./(x>=0) .* real(x.^(1/2));

计算这个的最快方式需要使用一个常规函数(而不是在 OP 中使用的匿名函数)。它会像这样:

function y = sqrt_or_nan(x)
y = nan(size(x));
index = x < 0;
y(index) = sqrt(x(index));

这避免了重复计算和不必要的计算,并使用 sqrt 而不是 .^(1/2)(我假设 sqrt 更快,尽管我没有计时验证)。

英文:

The problem with the code as given is that NaN times anything is NaN. NaN propagates through all calculations, by design; it's an error condition.

(Another problem with the code is that it computes the matrix multiplication and the matrix exponent. Use the element-wise operators .* and .^ instead: (x&gt;=0) .* x.^(1/2).)

Typically you'd accomplish your goal in two lines:

y = x.^(1/2);
y(x&lt;0) = NaN;

But for this particular case we can create a NaN where x&lt;0 by dividing x&gt;=0 by itself: (x&gt;=0)./(x&gt;=0) .* x.^(1/2). The result of the division is either NaN or 1, which multiplied by the square root of x yields either NaN or the square root of x.

Here I found yet another issue: x.^(1/2) is complex if any element of x is negative. So we need to take the real component of its result:

y = @(x) (x&gt;=0)./(x&gt;=0) .* real(x.^(1/2));

The fastest way to compute this would need to be in a regular function (as opposed to an anonymous function as you have in the OP. It would look like this:

function y = sqrt_or_nan(x)
y = nan(size(x));
index = x &lt; 0;
y(index) = sqrt(x(index));

This avoids duplicate computations and unnecessary computations, and uses sqrt instead of .^(1/2) (which I presume is faster, though I haven't timed it).

huangapple
  • 本文由 发表于 2023年7月10日 12:15:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76650650.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定