Producing a NaN only where there is a NaN, zero otherwise
1 次查看(过去 30 天)
显示 更早的评论
This interesting question came up for me today. I was looking for a simple expression that can be used in a function handle, one that produces a NaN only for elements that are already NaN, but I want it to return 0 for any other element, including +/- inf.
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
That should qualify as a good list of the possible numbers in MATLAB that might be of interest.
I want my function to generate a result as the vector: [0 0 0 0 0 0 0 0 0 0 0 NaN].
For example, this fails:
broken1 = @(X) 0*X;
broken1(X)
Though it is close. It suffers because 0*inf generates a NaN. An as pretty one is:
broken2 = @(X) X - X;
broken2(X)
It fails for a similar reason, because inf-inf produces NaN.
A valid solution should work for arrays of any shape or size of course. Yes, it is trivial to write if I do it in an m-file. Thus...
nanZ(X)
function res = nanZ(X)
% returns a NaN ONLY for elements of X that are NaN. All other elements will generate zero.
res = zeros(size(X));
res(isnan(X)) = NaN;
end
As I said, trivial if I use an m-flle. More difficult if I wish to use a function handle. It may be a blind spot on my part. But as a puzzle, can you write a simple, robust one line expression to produce my desired result, expressed as a function handle? Vectorized, of course.
And yes, I'll admit this question has essentially zero value, since a valid solution exists in an m-file form. Have fun! (I'll post a spoiler as an answer if people cannot find a better solution than the one I found. My final solution required only 9 characters, but it was definitely non-obvious.)
2 个评论
回答(6 个)
Stephen23
2021-2-22
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
Y = 0./(X==X)
4 个评论
the cyclist
2021-2-22
编辑:the cyclist
2021-2-22
0./eq(X,X)
is a nice variant of this, but one additional character
Gustavo Lunardon
2021-3-24
Added as an answer rather than a comment now
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
broken1 = @(X) 0./X.^0;
broken1(X)
Also works, 7 characters
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
broken1 = @(X) 0*X.^0;
broken1(X)
Works as well with 6 characters
Advantage is that you can put any number different than zero in the other elements by changing the multiplier
1 个评论
the cyclist
2021-3-24
Very nice!
It's a darn shame that
not(NaN)
does not yield NaN, because "NaN cannot be converted to logical". If it did, then
~X.^0
would be a sublime 5-character solution.
the cyclist
2021-2-22
编辑:the cyclist
2021-2-22
First attempt:
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
broken = @(x) 1./((isnan(x)-1)/0); % 19 characters
broken(X)
0 个评论
the cyclist
2021-2-22
Second attempt ...
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
broken = @(x) 0./(isnan(x)-1); % 15 characters
broken(X)
2 个评论
the cyclist
2021-2-23
I overlooked the obvious improvement to this one:
broken = @(x) 0./~isnan(x); % 12 characters
I like the fact that this one avoids the annoying denominator parentheses
Jan
2021-3-24
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
V = [0, NaN];
F = @(X) V(isnan(X) + 1);
F(X)
0 个评论
John D'Errico
2021-2-22
编辑:John D'Errico
2021-2-22
2 个评论
Gustavo Lunardon
2021-3-24
编辑:Gustavo Lunardon
2021-3-24
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
broken1 = @(X) 0./X.^0;
broken1(X)
Also works, 7 characters
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
broken1 = @(X) 0*X.^0;
broken1(X)
Works as well with 6 characters
Advantage is that you can put any number different than zero in the other elements by changing the multiplier
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Numeric Types 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!