英文:
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 >= 0: y = x^(1/2)
if x< 0: y = NaN
I have tried below code, which clearly does not work.
y = @(x) (x>=0) * x.^(1/2) - NaN* (x<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>=0) .* x^(1/2) - NaN.* (x<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>=0) = x(x>=0).^(1/2);
x(x<0) = NaN;
>> 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>=0) .* x.^(1/2)
.)
Typically you'd accomplish your goal in two lines:
y = x.^(1/2);
y(x<0) = NaN;
But for this particular case we can create a NaN where x<0
by dividing x>=0
by itself: (x>=0)./(x>=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>=0)./(x>=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 < 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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论