Loren on the Art of MATLAB

Turn ideas into MATLAB

No Infs, NaNs, or Bits 5

Posted by Loren Shure,

You may have heard the phrase "no ifs, ands, or buts" - meaning that there whatever the issue is, there is a definitive, non-negotiable answer or outcome. I heard it often when trying to persuade my parents to allow me to do something they didn't want me to do. Today when I heard someone use that phrase, what I sort of heard instead was "no |Inf|s, |NaN|s, or bits". So I will talk about those values and types today.


Talking about infinity

In many applications, an infinite result is not acceptable. I do remember a quantum physics final exam question where I did end up with Inf, but then realized I needed to take the arctangent (atan2), and all was good with my answer. How do we detect the presence of infinity? Using one of the many is* functions!

Let me throw a bunch of values into an array so we can check them for various values or conditions.

vals = [-Inf 0 pi 17 42 Inf NaN]
vals =
      -Inf         0    3.1416   17.0000   42.0000       Inf       NaN

Notice that isinf correctly finds positive and negative infinite values. First I see which ones are infinite, then I select them for display, via logical indexing.

nonInfVals = isinf(vals)
myInfVals = vals(nonInfVals)
nonInfVals =
     1     0     0     0     0     1     0
myInfVals =
  -Inf   Inf

Instead, I can just find the finite values.

finiteVals = vals(isfinite(vals))
finiteVals =
         0    3.1416   17.0000   42.0000

For a nice use of -Inf in an algorithm, check out this post, where a -Inf results indicate that no solution smaller than the threshold is available.

And now for the NaNs

And, of course, there's my longstanding friend isnan, a great tool for selecting the NaN values, and along with logical indexing, replacing or removing them.

replacedNaNvals = vals;
replacedNaNvals(isnan(replacedNaNvals)) = -999
replacedNaNvals =
      -Inf         0    3.1416   17.0000   42.0000       Inf -999.0000


MATLAB does have some functions for operating on arrays bit-wise, but does not have a bit datatype.

While MATLAB doesn't have a bit datatype, it does have some integer types. Let's see how we might use this. I will create a cell array with different types in each cell so we can explore a bunch of types in one call.

mycell = {magic(2) uint8(magic(2)) 'buts'; ...
    int32(magic(3)) [Inf -Inf] NaN; ...
    logical(eye(2)) {magic(2)} {uint8(magic(2))}}
mycell = 
    [2x2 double ]    [2x2 uint8 ]    'buts'    
    [3x3 int32  ]    [1x2 double]    [     NaN]
    [2x2 logical]    {1x1 cell  }    {1x1 cell}

Let's see what isinteger can tell us.

integerCells = cellfun(@isinteger, mycell)
integerCells =
     0     1     0
     1     0     0
     0     0     0

Notice that this function, isinteger, essentially works on each separate array, rather than elementwise, because it is answering a question about the type of the array, not individual values. Some is* functions act elementwise, and others act on an array as a whole.

Casting for an answer

There are a few more interesting functions in the functions covering numeric types, particularly, typecast and cast. typecast allows you to convert data types without changing the underlying data. cast lets you cast the variable to a different datatype. And swapbytes let's you swap the byte ordering, particularly useful for transforming the endianness of data.

My bet...

No ifs ands or buts - I am sure many of you already make good use of a few of these Infs, NaNs, and bit functions. What kind of data value wrangling do you do with MATLAB? I mean things like I've mentioned in this post, not as "big" as peak or outlier detection. MATLAB and add-on products do have many of those capabilities. I'm looking for the "little" things. Let me know here.

Get the MATLAB code

Published with MATLAB® R2015b


Comments are closed.

5 CommentsOldest to Newest

bshoelso replied on : 1 of 5
Hi Loren, Years before I joined MathWorks, a frequent contributor to CSSM pointed out that isnan(X) could be readily replaced by X~=X. I thought that was particularly clever: nan~=nan is true; nan ==nan is false. We subsequently had some discussions about whether that was a "safe" strategy--or whether it was likely to break in a future release. (Still works!) Any thoughts--on the performance or the utility of that approach? Cheers, Brett
Tektotherriggen replied on : 2 of 5
Brett, using "isnan" is better because it is self-documenting. It is semi-obvious from the name what it does; if not, the user can select it and ask the Matlab editor for help. "x~=x" will not be obvious to all programmers - you would have to add a comment to explain its action, which removes any advantage in brevity. You might even get a novice who doesn't know about NaNs, and replaces the statement with a "false" constant! Of course, if that trick does evaluate slightly faster, it is still worth using for very large loops or arrays. Just comment it well!
Adam replied on : 3 of 5
I did a quick test with a timeit function for both of those options since I was interested. I tried with various arrays of up to 5000-squared in size with random elements set to be NaNs. Generally the two techniques were similar in speed, but the isnan approach was coming out faster in almost all cases, if only by a small margin. It is also a nice clear function whereas X ~= X is one of those clever, but unintuitive bits of code that can so easily be produced in Matlab so I think I would always favour it personally. My colleagues are often complaining to me when I write 'overly clever code' in Matlab!
Loren Shure replied on : 4 of 5
Brett- I am all for isnan, as the others said, for readability, maintainability, AND I believe it is generally a bit faster. I think your approach is safe, and always will be, but cryptic for many users, as both other posters mention. --Loren
Brett replied on : 5 of 5
Thanks, everyone. For the record, I agree with all of these assessments. Still, I think X=X(X==X) is an interesting construct, and makes for a good conversation! ;) Brett