In C you can test to see if a double if NaN using isnan(x)
. However many places online, including for example this SO answer say that you can simply use x!=x
NaN as the only value x
with the property x!=x
is an IEEE 754 guarantee. Whether it is a faithful test to recognize NaN
in C boils down to how closely the representation of variables and the operations are mapped to IEEE 754 formats and operations in the compiler(s) you intend to use.
You should in particular worry about “excess precision” and the way compilers deal with it. Excess precision is what happens when the FPU only conveniently supports computations in a wider format than the compiler would like to use for float
and double
types. In this case computations can be made at the wider precision, and rounded to the type's precision when the compiler feels like it in an unpredictable way.
The C99 standard defined a way to handle this excess precision that preserved the property that only NaN was different from itself, but for a long time after 1999 (and even nowadays when the compiler's authors do not care), in presence of excess precision, x != x
could possibly be true for any variable x
that contains the finite result of a computation, if the compiler chooses to round the excess-precision result of the computation in-between the evaluation of the first x
and the second x
.
This report describes the dark times of compilers that made no effort to implement C99 (either because it wasn't 1999 yet or because they didn't care enough).
This 2008 post describes how GCC started to implement the C99 standard for excess precision in 2008. Before that, GCC could provide one with all the surprises described in the aforementioned report.
Of course, if the target platform does not implement IEEE 754 at all, a NaN value may not even exist, or exist and have different properties than specified by IEEE 754. The common cases are a compiler that implements IEEE 754 quite faithfully with FLT_EVAL_METHOD set to 0, 1 or 2 (all of which guarantee that x != x
iff x
is NaN), or a compiler with a non-standard implementation of excess precision, where x != x
is not a reliable test for NaN.
Please refer to the normative section Annex F: IEC 60559 floating-point arithmetic of the C standard:
F.1 Introduction
An implementation that defines
__STDC_IEC_559__
shall conform to the specifications in this annex.Implementations that do not define
__STDC_IEC_559__
are not required to conform to these specifications.
F.9.3 Relational operators
The expression
x ≠ x
is true ifx
is aNaN
.The expression
x = x
is false ifX
is aNan
.
F.3 Operators and functions
The
isnan
macro in<math.h>
provides theisnan
function recommended in the Appendix to IEC 60559.