是否存在isnan()函数?
注:我在MinGW(如果这有区别的话)。
我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。
是否存在isnan()函数?
注:我在MinGW(如果这有区别的话)。
我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。
当前回答
下面的代码使用NAN(所有指数位集合,至少一个小数位集合)的定义,并假设sizeof(int) = sizeof(float) = 4。你可以在维基百科中查找NAN的详细信息。
bool IsNan(浮点值) { return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000; }
其他回答
一个可能的解决方案,不依赖于特定的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) );
}
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的整个数学工具包,它有许多有用的工具,并且正在快速增长。
此外,当处理浮点和非浮点时,查看数字转换可能是一个好主意。
考虑到(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)
我不确定这是如何受到快速数学的影响,所以你的里程可能会有所不同。
您可以使用在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++进行了测试。
南预防
我对这个问题的回答是不要对nan使用追溯检查。取而代之的是对表单0.0/0.0的划分使用预防性检查。
#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是0.f/0运算的结果。F,或0.0/0.0。Nan是代码稳定性的一个可怕的克星,必须非常小心地检测和防止1。nan不同于普通数的特性:
Nan是有毒的,(5* Nan = Nan) Nan不等于任何东西,甚至不等于它本身(Nan != Nan) Nan不大于任何东西(Nan !> 0) Nan不小于任何值(Nan !< 0)
最后列出的2个属性是反逻辑的,将导致依赖于与nan数比较的代码的奇怪行为(最后3个属性也很奇怪,但您可能永远不会看到x != x ?)在你的代码中(除非你在检查nan(不可靠))。
在我自己的代码中,我注意到nan值往往会产生难以发现的错误。(请注意,这不是inf或-inf的情况。(-inf < 0)返回TRUE, (0 < inf)返回TRUE,甚至(-inf < inf)返回TRUE。因此,在我的经验中,代码的行为通常仍然是理想的)。
在奶奶手下该怎么办
您希望在0.0/0.0下发生的事情必须作为特殊情况处理,但是您所做的事情必须取决于您期望从代码中得到的数字。
在上面的例子中,(0.f/FLT_MIN)的结果基本上是0。你可能想让0.0/0.0生成HUGE。所以,
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.
在上面,如果x = 0。F, inf会导致(实际上如上所述,它具有相当好的/非破坏性行为)。
记住,整数除以0会导致运行时异常。所以你必须总是检查整数除以0。仅仅因为0.0/0.0悄悄地计算为nan并不意味着您可以偷懒,在它发生之前不检查0.0/0.0。
通过x != x检查nan有时是不可靠的(x != x被一些破坏IEEE遵从性的优化编译器剥离,特别是当- fast-math开关启用时)。