Innehållsförteckning RecentChanges News ElispArea HowTo Problems Suggestions

NotANumber

In GNU Emacs, there are some numbers that you might not think of as numbers. These include the FloatingPoint values positive infinity (`1.0e+INF’), negative infinity (`-1.0e+INF’), and not-a-number (`0.0e+NaN’).

NaN, in particular, can be confusing: it’s a number that says it is “not a number”! So, for instance, `(numberp 0.0e+NaN)’ returns ‘t’, not ‘nil’.

I was bitten by this “gotcha” recently. I had something like this, where ‘bar’ was sometimes 0.0:

  (if (condition-case nil
          (setq foo (/ toto bar))
        (arith-error nil)) ; Return nil if an error, such as divide by zero.
       ...)

In GNU Emacs 20 and some revisions of GNU Emacs 21, this returns ‘nil’ when ‘bar’ is zero. In a recent snapshot of GNU Emacs 22 (CVS), it simply sets ‘foo’ to the number (quotient) `0.0e+NaN’, which is non-‘nil’.

After fiddling a bit, this is what I came up with:

  (if (and (condition-case nil
               (setq foo (/ toto bar))
             (arith-error nil)) ; Return nil if an error.
           (not (equal 0.0e+NaN foo))) ; foo must be a number, not NaN
       ...)

This works – you can test whether or not an object is NaN by testing whether it is ‘equal’ to `0.0e+NaN’ (the mantissa here, 0.0, is irrelevant; 73.4e+NaN would work as well).

Another sexp equivalent to (equal 0.0e+NaN foo) is this: (and (numberp x) (/= x x)). The latter expression uses the “trick” that NaN is a number that is not `=’ to itself.

Note the use of ‘equal’ and ‘/=’ above. I prefer the sexp (equal 0.0e+NaN foo), as I think it is a clearer test for whether ‘foo’ is NaN. You could substitute ‘eql’ for ‘equal’ here, but you cannot substitute ‘eq’ or `=’.

DrewAdams


CategoryCode