Click here to Skip to main content
15,867,323 members
Articles / Programming Languages / C
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
4.80/5 (7 votes)
12 Apr 2016CPOL2 min read 28.4K   107   12   1
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)


Written By
Software Developer (Senior)
Singapore Singapore
Shao Voon is from Singapore. His interest lies primarily in computer graphics, software optimization, concurrency, security, and Agile methodologies.

In recent years, he shifted focus to software safety research. His hobby is writing a free C++ DirectX photo slideshow application which can be viewed here.

Comments and Discussions

 
QuestionShouldn't this be catched as an error by compilers ? Pin
GilbouFR5-Dec-16 4:19
GilbouFR5-Dec-16 4:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.