是否存在isnan()函数?

注:我在MinGW(如果这有区别的话)。

我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。


当前回答

IEEE标准说 当指数都是1时 而且 尾数不是零, 该号码是一个NaN。 Double是1个符号位,11个指数位和52个尾数位。 做一点检查。

其他回答

一个可能的解决方案,不依赖于特定的IEEE表示NaN使用如下:

template<class T>
bool isnan( T f ) {
    T _nan =  (T)0.0/(T)0.0;
    return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}

如果你的编译器支持c99扩展,有一个std::isnan,但我不确定mingw是否支持。

下面是一个小函数,如果你的编译器没有标准函数,它应该可以工作:

bool custom_isnan(double var)
{
    volatile double d = var;
    return d != d;
}
inline bool IsNan(float f)
{
    const uint32 u = *(uint32*)&f;
    return (u&0x7F800000) == 0x7F800000 && (u&0x7FFFFF);    // Both NaN and qNan.
}

inline bool IsNan(double d)
{
    const uint64 u = *(uint64*)&d;
    return (u&0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && (u&0xFFFFFFFFFFFFFULL);
}

如果sizeof(int)为4,sizeof(long long)为8,则此方法有效。

在运行时,它只是比较,类型转换不需要任何时间。它只是改变比较标志配置来检查是否相等。

如此:

#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;
}

输出:isnan

考虑到(x != x)对于NaN并不总是保证的(比如如果使用- fast-math选项),我一直在使用:

#define IS_NAN(x) (((x) < 0) == ((x) >= 0))

数字不能同时< 0和>= 0,所以实际上只有当数字既不小于也不大于或等于0时,这个检查才会通过。基本上没有数字,或者NaN。

如果你喜欢,你也可以使用这个:

#define IS_NAN(x) (!((x)<0) && !((x)>=0)

我不确定这是如何受到快速数学的影响,所以你的里程可能会有所不同。