Checking if a double (or float) is NaN in C++

Is there an isnan() function?

PS.: I'm in MinGW (if that makes a difference).

I had this solved by using isnan() from <math.h>, which doesn't exist in <cmath>, which I was #includeing at first.


According to the IEEE standard, NaN values have the odd property that comparisons involving them are always false. That is, for a float f, f != f will be true only if f is NaN.

Note that, as some comments below have pointed out, not all compilers respect this when optimizing code.

For any compiler which claims to use IEEE floating point, this trick should work. But I can't guarantee that it will work in practice. Check with your compiler, if in doubt.


There is no isnan() function available in current C++ Standard Library. It was introduced in C99 and defined as a macro not a function. Elements of standard library defined by C99 are not part of current C++ standard ISO/IEC 14882:1998 neither its update ISO/IEC 14882:2003.

In 2005 Technical Report 1 was proposed. The TR1 brings compatibility with C99 to C++. In spite of the fact it has never been officially adopted to become C++ standard, many (GCC 4.0+ or Visual C++ 9.0+ C++ implementations do provide TR1 features, all of them or only some (Visual C++ 9.0 does not provide C99 math functions).

If TR1 is available, then cmath includes C99 elements like isnan(), isfinite(), etc. but they are defined as functions, not macros, usually in std::tr1:: namespace, though many implementations (i.e. GCC 4+ on Linux or in XCode on Mac OS X 10.5+) inject them directly to std::, so std::isnan is well defined.

Moreover, some implementations of C++ still make C99 isnan() macro available for C++ (included through cmath or math.h), what may cause more confusions and developers may assume it's a standard behaviour.

A note about Viusal C++, as mentioned above, it does not provide std::isnan neither std::tr1::isnan, but it provides an extension function defined as _isnan() which has been available since Visual C++ 6.0

On XCode, there is even more fun. As mentioned, GCC 4+ defines std::isnan. For older versions of compiler and library form XCode, it seems (here is relevant discussion), haven't had chance to check myself) two functions are defined, __inline_isnand() on Intel and __isnand() on Power PC.


First solution: if you are using C++11

Since this was asked there were a bit of new developments: it is important to know that std::isnan() is part of C++11

Synopsis

Defined in header <cmath>

bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)

Determines if the given floating point number arg is not-a-number (NaN).

Parameters

arg: floating point value

Return value

true if arg is NaN, false otherwise

Reference

http://en.cppreference.com/w/cpp/numeric/math/isnan

Please note that this is incompatible with -fast-math if you use g++, see below for other suggestions.


Other solutions: if you using non C++11 compliant tools

For C99, in C, this is implemented as a macro isnan(c)that returns an int value. The type of x shall be float, double or long double.

Various vendors may or may not include or not a function isnan().

The supposedly portable way to check for NaN is to use the IEEE 754 property that NaN is not equal to itself: i.e. x == x will be false for x being NaN.

However the last option may not work with every compiler and some settings (particularly optimisation settings), so in last resort, you can always check the bit pattern ...


There is also a header-only library present in Boost that have neat tools to deal with floating point datatypes

#include <boost/math/special_functions/fpclassify.hpp>

You get the following functions:

template <class T> bool isfinite(T z);
template <class T> bool isinf(T t);
template <class T> bool isnan(T t);
template <class T> bool isnormal(T t);

If you have time then have a look at whole Math toolkit from Boost, it has many useful tools and is growing quickly.

Also when dealing with floating and non-floating points it might be a good idea to look at the Numeric Conversions.