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
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.
It seems to me that the best truly cross-platform approach would be to use a union and to test the bit pattern of the double to check for NaNs.
I have not thoroughly tested this solution, and there may be a more efficient way of working with the bit patterns, but I think that it should work.
#include <stdint.h>
#include <stdio.h>
union NaN
{
uint64_t bits;
double num;
};
int main()
{
//Test if a double is NaN
double d = 0.0 / 0.0;
union NaN n;
n.num = d;
if((n.bits | 0x800FFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF)
{
printf("NaN: %f", d);
}
return 0;
}
There are three "official" ways: posix isnan
macro, c++0x isnan
function template, or visual c++ _isnan
function.
Unfortunately it's rather impractical to detect which of those to use.
And unfortunately, there's no reliable way to detect whether you have IEEE 754 representation with NaNs. The standard library offers an official such way (numeric_limits<double>::is_iec559
). But in practice compilers such as g++ screw that up.
In theory one could use simply x != x
, but compilers such as g++ and visual c++ screw that up.
So in the end, test for the specific NaN bitpatterns, assuming (and hopefully enforcing, at some point!) a particular representation such as IEEE 754.
EDIT: as an example of "compilers such as g++ … screw that up", consider
#include <limits>
#include <assert.h>
void foo( double a, double b )
{
assert( a != b );
}
int main()
{
typedef std::numeric_limits<double> Info;
double const nan1 = Info::quiet_NaN();
double const nan2 = Info::quiet_NaN();
foo( nan1, nan2 );
}
Compiling with g++ (TDM-2 mingw32) 4.4.1:
C:\test> type "C:\Program Files\@commands\gnuc.bat" @rem -finput-charset=windows-1252 @g++ -O -pedantic -std=c++98 -Wall -Wwrite-strings %* -Wno-long-long C:\test> gnuc x.cpp C:\test> a && echo works... || echo !failed works... C:\test> gnuc x.cpp --fast-math C:\test> a && echo works... || echo !failed Assertion failed: a != b, file x.cpp, line 6 This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. !failed C:\test> _
The IEEE standard says
when the exponent is all 1
s
and
the mantissa is not zero,
the number is a NaN
.
Double is 1
sign bit, 11
exponent bits and 52
mantissa bits.
Do a bit check.
A possible solution that would not depend on the specific IEEE representation for NaN used would be the following:
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}
As comments above state a != a will not work in g++ and some other compilers, but this trick should. It may not be as efficient, but it's still a way:
bool IsNan(float a)
{
char s[4];
sprintf(s, "%.3f", a);
if (s[0]=='n') return true;
else return false;
}
Basically, in g++ (I am not sure about others though) printf prints 'nan' on %d or %.f formats if variable is not a valid integer/float. Therefore this code is checking for the first character of string to be 'n' (as in "nan")