是否存在isnan()函数?
注:我在MinGW(如果这有区别的话)。
我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。
是否存在isnan()函数?
注:我在MinGW(如果这有区别的话)。
我使用isnan()从<math.h>解决了这个问题,这在<cmath>中不存在,我一开始是#包括在内的。
当前回答
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的整个数学工具包,它有许多有用的工具,并且正在快速增长。
此外,当处理浮点和非浮点时,查看数字转换可能是一个好主意。
其他回答
如果你的编译器支持c99扩展,有一个std::isnan,但我不确定mingw是否支持。
下面是一个小函数,如果你的编译器没有标准函数,它应该可以工作:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
如此:
#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
在我看来,最好的真正跨平台的方法是使用联合,并测试double的位模式来检查nan。
我还没有彻底测试这个解决方案,可能有一种更有效的方法来处理比特模式,但我认为它应该有效。
#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;
}
南预防
我对这个问题的回答是不要对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开关启用时)。
考虑到(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)
我不确定这是如何受到快速数学的影响,所以你的里程可能会有所不同。