Is there an isnan() function?
PS.: I\'m in MinGW (if that makes a difference).
I had this solved by using isnan() from
, which doe
My answer to this question is don't use retroactive checks for nan
. Use preventive checks for divisions of the form 0.0/0.0
instead.
#include <float.h>
float x=0.f ; // I'm gonna divide by x!
if( !x ) // Wait! Let me check if x is 0
x = FLT_MIN ; // oh, since x was 0, i'll just make it really small instead.
float y = 0.f / x ; // whew, `nan` didn't appear.
nan
results from the operation 0.f/0.f
, or 0.0/0.0
. nan
is a terrible nemesis to the stability of your code that must be detected and prevented very carefully1. The properties of nan
that are different from normal numbers:
nan
is toxic, (5*nan
=nan
)nan
is not equal to anything, not even itself (nan
!= nan
)nan
not greater than anything (nan
!> 0)nan
is not less than anything (nan
!< 0)The last 2 properties listed are counter-logical and will result in odd behavior of code that relies on comparisons with a nan
number (the 3rd last property is odd too but you're probably not ever going to see x != x ?
in your code (unless you are checking for nan (unreliably))).
In my own code, I noticed that nan
values tend to produce difficult to find bugs. (Note how this is not the case for inf
or -inf
. (-inf
< 0) returns TRUE
, ( 0 < inf
) returns TRUE, and even (-inf
< inf
) returns TRUE. So, in my experience, the behavior of the code is often still as desired).
What you want to happen under 0.0/0.0
must be handled as a special case, but what you do must depend on the numbers you expect to come out of the code.
In the example above, the result of (0.f/FLT_MIN
) will be 0
, basically. You may want 0.0/0.0
to generate HUGE
instead. So,
float x=0.f, y=0.f, z;
if( !x && !y ) // 0.f/0.f case
z = FLT_MAX ; // biggest float possible
else
z = y/x ; // regular division.
So in the above, if x were 0.f
, inf
would result (which has pretty good/nondestructive behavior as mentioned above actually).
Remember, integer division by 0 causes a runtime exception. So you must always check for integer division by 0. Just because 0.0/0.0
quietly evaluates to nan
doesn't mean you can be lazy and not check for 0.0/0.0
before it happens.
1 Checks for nan
via x != x
are sometimes unreliable (x != x
being stripped out by some optimizing compilers that break IEEE compliance, specifically when the -ffast-math
switch is enabled).
Considering that (x != x) is not always guaranteed for NaN (such as if using the -ffast-math option), I've been using:
#define IS_NAN(x) (((x) < 0) == ((x) >= 0))
Numbers can't be both < 0 and >= 0, so really this check only passes if the number is neither less than, nor greater than or equal to zero. Which is basically no number at all, or NaN.
You could also use this if you prefer:
#define IS_NAN(x) (!((x)<0) && !((x)>=0)
I'm not sure how this is affected by -ffast-math though, so your mileage may vary.
As for me the solution could be a macro to make it explicitly inline and thus fast enough. It also works for any float type. It bases on the fact that the only case when a value is not equals itself is when the value is not a number.
#ifndef isnan
#define isnan(a) (a != a)
#endif
You can use the isnan()
function, but you need to include the C math library.
#include <cmath>
As this function is part of C99, it is not available everywhere. If your vendor does not supply the function, you can also define your own variant for compatibility.
inline bool isnan(double x) {
return x != x;
}
This works:
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
char ch='a';
double val = nan(&ch);
if(isnan(val))
cout << "isnan" << endl;
return 0;
}
output: isnan
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.