Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C

C99 and C++11: Use isnan to test for NaN

4.80/5 (7 votes)
12 Apr 2016CPOL2 min read 29.4K   109  
Never test for NaN by comparing it with NaN literal

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?

C++
if (NAN == NAN)
    cout << "same" << endl;
else
    cout << "diff" << endl;
	
// output: diff

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.

C++
float ans = sqrtf(-1.0f);
if (ans == NAN)
    cout << "same" << endl;
else
    cout << "diff" << endl;

// output: diff

if (isnan(ans))
    cout << "is NaN" << endl;
else
    cout << "is not NaN" << endl;

// output: is NaN

if (_isnan(ans)) // VC13 team did not remove _isnan for legacy code which was calling it
    cout << "is NaN" << endl;
else
    cout << "is not NaN" << endl;

// output: is NaN

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.

C++
if (numeric_limits<float>::signaling_NaN() == numeric_limits<float>::signaling_NaN())
    cout << "signaling NaN" << endl;
else
    cout << "is not signaling NaN" << endl;

// output: is not signaling NaN

if (numeric_limits<float>::quiet_NaN() == numeric_limits<float>::quiet_NaN())
    cout << "quiet NaN" << endl;
else
    cout << "is not quiet NaN" << endl;

// output: is not quiet NaN

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.

C++
#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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)