NaN is not-a-number floating point. As rule of thumb, isnan
function should always be used to test for NaN instead of directly comparing the floating number with NaN literal. isnan
is available in Visual C++ 2013 and newer. Developers who are using an earlier version of Visual C++, can use _isnan
. Consider the code below! Comparing NaN with NaN, what would be the output?
if (NAN == NAN)
cout << "same" << endl;
else
cout << "diff" << endl;
The output is "diff"
. This is exactly the reason we cannot test for NaN equality because comparing NaN literal with itself will return false! GCC has the same behaviour. In the code below, a NaN is generated by the square root of a negative number and we check for NaN using the equality comparison and isnan
function.
float ans = sqrtf(-1.0f);
if (ans == NAN)
cout << "same" << endl;
else
cout << "diff" << endl;
if (isnan(ans))
cout << "is NaN" << endl;
else
cout << "is not NaN" << endl;
if (_isnan(ans)) cout << "is NaN" << endl;
else
cout << "is not NaN" << endl;
The output is "diff"
, "is NaN"
and "is NaN"
.
There are 2 types of NaNs: signalling and quiet. The IEEE specification differentiates between signaling NaNs and quiet NaNs. Signaling NaNs will generate a exception when used in an arithmetic operation. Quiet NaNs will propagate through the chain of most floating-point operation without raising an exception.. Even comparing Signaling NaNs or Quiet NaNs equality has the same behaviour.
if (numeric_limits<float>::signaling_NaN() == numeric_limits<float>::signaling_NaN())
cout << "signaling NaN" << endl;
else
cout << "is not signaling NaN" << endl;
if (numeric_limits<float>::quiet_NaN() == numeric_limits<float>::quiet_NaN())
cout << "quiet NaN" << endl;
else
cout << "is not quiet NaN" << endl;
Note: I skipped some checks in the above code. Before signaling_NaN()
or quiet_NaN()
is called, there should be checks for numeric_limits<float>::is_iec559
, numeric_limits<float>::has_signaling_NaN
and numeric_limits<float>::has_quiet_NaN
. IEC 60559 is synonymous with IEEE 754 standard for floating point; IEC 60559 is also sometimes referred to as IEC 559.
Important Note For Earlier Visual Studio
For those of us running earlier version of Visual Studio (2005 - 2012), NAN
is not defined and isnan
should be commented out. You can copy and paste the code below from VS2013 to define NAN
. numeric_limits
template class is not included in VS2005 and VS2008 so the code should be commented out.
#ifndef _HUGE_ENUF
#define _HUGE_ENUF 1e+300 /* _HUGE_ENUF*_HUGE_ENUF must overflow */
#endif /* _HUGE_ENUF */
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) /* causes warning C4756: overflow in constant arithmetic (by design) */
#define NAN ((float)(INFINITY * 0.0F))
Points of Interest
C language version of isnan
is a macro, not template function as in C++. For C99, __STDC_IEC_559__
macro will be present if there is support for IEEE 754. There are some other IEEE 754 functions you should definitely check them out!
- isfinite checks if the given number has finite value
- isinf checks if the given number is infinite
- isnormal checks if the given number is normal
References
- Write Portable Code (Chapter 6: Floating Point) by Brian Hook
- 21st Century C by Ben Klemens
- Programming Massively Parallel Processors, 2nd Edition (Chapter 7: Floating-Point Considerations) by David B. Kirk; Wen-mei W. Hwu