Methods to create arrays of NaN

6 views (last 30 days)
Michael Brown
Michael Brown on 15 Jun 2022
Answered: Steven Lord on 16 Jun 2022
I often need to create arrays of NaNs, e.g. for preallocation. I have always done that by using the zeros function, and adding NaN, e.g:
vec1 = zeros(10,1)+NaN % vector, zeros+NaN method
vec1 = 10×1
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
arr1 = zeros(10,10)+NaN % matrix, zeros+NaN method
arr1 = 10×10
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
However, I recently discovered the "nan" function, which is certainly more straight forward:
vec2 = nan(10,1) % vector, nan method
vec2 = 10×1
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
arr2 = nan(10,10) % matrix, nan method
arr2 = 10×10
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
I feel a bit silly that I've only just recently discovered the "nan" function given my reliance on arrays of NaNs. I can only surmise that as I was learning Matlab using colleagues' code as reference, I saw the zeros()+NaN method and it stuck. Regardless, are the outputs (vs. syntax, execution time, readability) of the two methods identical? It appears that they yield identical results, but I have come to learn that there can be nuances with NaNs and how they are represented etc., and just wanted to confirm. Apologies if this is a silly question, and thank you for the sanity check.
  4 Comments
dpb
dpb on 15 Jun 2022
To amplify, just a little; the use of NaN in in any math operation converts the output of whatever was there, finite or not, to NaN. It's a wasted operation and may trigger an extra memory copy, but the result will be the same.

Sign in to comment.

Answers (3)

Rik
Rik on 15 Jun 2022
Edited: Rik on 16 Jun 2022
In very old releases (prior to v7 (R14)) it was not possible to create arrays with NaN and inf. In those releases you had to use tricks like zeros(a,b)+NaN; to create arrays of NaNs.
But, as already mentioned, the results are identical. The JIT/EE could optimize away the overhead cause by the extra operations, but as the timings John showed in his answer, this is not (yet) the case.
So there is only a benefit if you need to keep your code compatible with very old releases. If not, you can shave a few milliseconds off every time you need a NaN array by calling it as a function.

John D'Errico
John D'Errico on 15 Jun 2022
Edited: John D'Errico on 15 Jun 2022
A NaN is a nan. A NaN by any other name, is still just a NaN.
But there are faster and slower ways to make them, and surely the nan function is the fastest, since it needs only allocate the memory and stuff NaNs into it. You could have done many things to create a NaN array. For example
A1 = NaN(100);
A2 = zeros(100) + NaN;
A3 = ones(100)*NaN;
A4 = sin(inf(100));
A5 = zeros(100)./zeros(100);
A6 = inf(100) - inf;
A7 = (-inf)./inf(100);
Many equally strange ways to do the job. All are identical to the first though.
num2hex(A1(1))
ans = 'fff8000000000000'
num2hex(A2(1))
ans = 'fff8000000000000'
num2hex(A3(1))
ans = 'fff8000000000000'
num2hex(A4(1))
ans = 'fff8000000000000'
num2hex(A5(1))
ans = 'fff8000000000000'
num2hex(A6(1))
ans = 'fff8000000000000'
num2hex(A7(1))
ans = 'fff8000000000000'
As you can see, a NaN really is just a NaN. The result is not dependent on how you get there. I could not even create a negative NaN.
Is there a time differential between the various schemes? Probably. Let me see...
n = 7500;
timeit(@() NaN(n))
ans = 0.1568
timeit(@() zeros(n) + NaN)
ans = 0.3420
timeit(@() ones(n)*NaN)
ans = 0.1804
timeit(@() sin(inf(n)))
ans = 0.3695
timeit(@() zeros(n)./zeros(n))
ans = 0.3822
timeit(@() inf(n) - inf)
ans = 0.1785
timeit(@() (-inf)./inf(n))
ans = 0.1791
So there are clearly some dumbish, yet creative ways to try to create a NaN. I'm not sure exactly why some of the methods above are much slower, but they do seem to be consistently all slower then the NaN function itself, as you would hope. In the end, the NaN function is easily the best, and for good reason.

Steven Lord
Steven Lord on 16 Jun 2022
You can check that the outputs of those two approaches are equal. The isequal function will return false since it does not consider NaN to be equal to anything, even another NaN (or the same NaN.) The isequaln function is the same as isequal except it considers NaN to be equal to NaN.
x = NaN + ones(1, 5)
x = 1×5
NaN NaN NaN NaN NaN
y = NaN(1, 5)
y = 1×5
NaN NaN NaN NaN NaN
isequal(x, y) % false
ans = logical
0
isequal(x, x) % false, the variable x is not equal to itself because of NaN
ans = logical
0
isequaln(x, y) % true
ans = logical
1

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!