是否存在isnan()函数?

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

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


当前回答

如果你的编译器支持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,则此方法有效。

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

Boost中还提供了一个仅头文件的库,该库具有处理浮点数据类型的简洁工具

#include <boost/math/special_functions/fpclassify.hpp>

你会得到以下函数:

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);

如果你有时间,那么看看Boost的整个数学工具包,它有许多有用的工具,并且正在快速增长。

此外,当处理浮点和非浮点时,查看数字转换可能是一个好主意。

您可以使用在limits标准库中定义的numeric_limits<float>::quiet_NaN()进行测试。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;
}

我不知道这是否适用于所有平台,因为我只在Linux上用g++进行了测试。

考虑到(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)

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

可以使用isnan()函数,但需要包含C数学库。

#include <cmath>

因为这个函数是C99的一部分,所以并不是所有地方都可用。如果您的供应商没有提供该功能,您也可以定义自己的变体以实现兼容性。

inline bool isnan(double x) {
    return x != x;
}