# Producing a NaN only where there is a NaN, zero otherwise

조회 수: 121(최근 30일)
John D'Errico 22 Feb 2021
댓글: the cyclist 24 Mar 2021 18:58
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)
ans = 1×12
NaN 0 0 0 0 0 0 0 0 0 NaN NaN
Though it is close. It suffers because 0*inf generates a NaN. An as pretty one is:
broken2 = @(X) X - X;
broken2(X)
ans = 1×12
NaN 0 0 0 0 0 0 0 0 0 NaN NaN
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)
ans = 1×12
0 0 0 0 0 0 0 0 0 0 0 NaN
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표시숨기기 이전 댓글 수: 1
John D'Errico 22 Feb 2021
Yes indeed.

댓글을 달려면 로그인하십시오.

### 답변(6개)

Stephen Cobeldick 22 Feb 2021
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
Y = 0./(X==X)
Y = 1×12
0 0 0 0 0 0 0 0 0 0 0 NaN
##### 댓글 수: 4표시숨기기 이전 댓글 수: 3
John D'Errico 22 Feb 2021
NIce. And it ties my solution of 9 characters. It will probably be more efficient than mine too.

댓글을 달려면 로그인하십시오.

Gustavo Lunardon 24 Mar 2021 18:47
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 24 Mar 2021 18:58
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 22 Feb 2021
편집: the cyclist 22 Feb 2021
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)
ans = 1×12
0 0 0 0 0 0 0 0 0 0 0 NaN
##### 댓글 수: 0표시숨기기 이전 댓글 수: -1

댓글을 달려면 로그인하십시오.

the cyclist 22 Feb 2021
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)
ans = 1×12
0 0 0 0 0 0 0 0 0 0 0 NaN
##### 댓글 수: 2표시숨기기 이전 댓글 수: 1
the cyclist 23 Feb 2021
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

댓글을 달려면 로그인하십시오.

John D'Errico 22 Feb 2021
편집: John D'Errico 22 Feb 2021
I'm always amazed at how many ways there are to accomplish anything in MATLAB. Here was my effort. It took me some time to think of my solution - why I posted the question. I had to find a call that would return a real number for any inputs, including inf and -inf. But I still needed it to return NaN for NaN input. Then i could just multiply by 0. atan fit perfectly. And since 0*NaN is still NaN, this was my solution:
X = [-inf, -1, -eps, 0, realmin, 2, 1+i, pi, flintmax, realmax, inf, NaN];
unbroken = @(X) 0*atan(X);
unbroken(X)
ans = 1×12
0 0 0 0 0 0 0 0 0 0 0 NaN
Only 9 characters. But I am sure there is a better solution yet. And mine might not be terribly computationally efficient.
(Sadly, things like 0*sin(X) fails, because sin(inf) is NaN. But that would have saved a character.)
##### 댓글 수: 2표시숨기기 이전 댓글 수: 1
Stephen Cobeldick 24 Mar 2021 17:03

댓글을 달려면 로그인하십시오.

Jan 24 Mar 2021 16:50
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)

댓글을 달려면 로그인하십시오.

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by