is there an isnan() function?
p.s. I'm in mingw (if that makes a difference)
UPDATE
Thanks for the responses
I had this solved by using isnan() form <math.h>
, which doesn't exist in <cmath>
, which I was #include
ing at first.
is there an isnan() function?
p.s. I'm in mingw (if that makes a difference)
UPDATE
Thanks for the responses
I had this solved by using isnan() form <math.h>
, which doesn't exist in <cmath>
, which I was #include
ing at first.
There is an std::isnan if you compiler supports c99 extensions, but I'm not sure if mingw does.
Here is a small function which should work if your compiler doesn't have the standard function:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
According to the IEEE standard, NaN values have the odd property that comparisons involving them are always false. That is, for a float f, f != f
will be true only if f is NaN.
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.
#ifndef isnan
inline bool isnan(double x) {
return x != x;
}
#endif
You can use numeric_limits<float>::quiet_NaN( )
defined in the limits
standard library to test with. There's a separate constant defined for double
.
#include <iostream>
#include <math.h>
#include <limits>
using namespace std;
int main( )
{
cout << "The quiet NaN for type float is: "
<< numeric_limits<float>::quiet_NaN( )
<< endl;
float f_nan = numeric_limits<float>::quiet_NaN();
if( isnan(f_nan) )
{
cout << "Float was Not a Number: " << f_nan << endl;
}
return 0;
}
I don't know if this works on all platforms, as I only tested with g++ on Linux.
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.
I believe that the "C++ way" to do this is to either use Boost or do something like:
#if I_HAVE_TR1
#include <cmath> // defines std::tr1::isnan<T>
#else
#include <limits>
namespace std { namespace tr1 {
template <class T>
inline bool isnan(T val) {
return ((std::numeric_limits<T>::has_quiet_NaN &&
(std::numeric_limits<T>::quiet_NaN() == val)) ||
(std::numeric_limits<T>::has_signaling_NaN &&
(std::numeric_limits<T>::signaling_NaN() == val));
}
}} // end namespace std::tr1
#endif
or some less readable variant of that. IIRC, TR1 added in all of the math goodness from C99. Unfortunately I can't recall how to properly detect if the compilation environment supports TR1 :(
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.