有一个isnan()函数吗?
PS .:我在MinGW (如果有帮助)。
我使用<math.h>
isnan()解决了这个问题,该问题在<cmath>
中不存在,而我最初是#include
。
#1楼
不依赖于所用NaN的特定IEEE表示的可能解决方案如下:
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}
#2楼
对我来说,解决方案可以是一个宏,使其显式内联,从而足够快。 它也适用于任何浮点类型。 它基于这样一个事实:当值不等于自身时,唯一的情况就是当值不是数字时。
#ifndef isnan
#define isnan(a) (a != a)
#endif
#3楼
第一个解决方案:如果您使用的是C ++ 11
自从有人问到这个问题以来,就有了一些新的发展:重要的是要知道std::isnan()
是C ++ 11的一部分
概要
定义于头文件<cmath>
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
确定给定的浮点数arg是否为非整数( NaN
)。
参量
arg
:浮点值
返回值
true
如果arg是NaN
, false
,否则
参考
http://en.cppreference.com/w/cpp/numeric/math/isnan
请注意,如果使用g ++,则它与-fast-math不兼容,请参见以下其他建议。
其他解决方案:如果使用不符合C ++ 11的工具
对于C99,在C中,将其实现为返回一个int值的宏isnan(c)
。 x
的类型应为float,double或long double。
各种供应商可能会或可能不会包含功能isnan()
。
检查NaN
可移植方法是使用NaN
不等NaN
自身的IEEE 754属性:即x == x
对于x
为NaN
将为假。
但是,最后一个选项可能不适用于每个编译器和某些设置(尤其是优化设置),因此,在万不得已时,您始终可以检查位模式...
#4楼
如上面的注释所述,!= a在g ++和某些其他编译器中不起作用,但是这种技巧应该可以。 它可能效率不高,但仍然是一种方法:
bool IsNan(float a)
{
char s[4];
sprintf(s, "%.3f", a);
if (s[0]=='n') return true;
else return false;
}
基本上,在g ++(尽管我不确定其他人)中,如果变量不是有效的整数/浮点数,printf将以%d或%.f格式打印'nan'。 因此,此代码检查字符串的第一个字符为“ n”(如“ nan”)
#5楼
南预防
我对这个问题的回答是, 不要对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
运算0.f/0.f
。 nan
对您的代码的稳定性是一个可怕的宿敌,必须非常仔细地对其进行检测和预防 1 。 nan
与普通数不同的属性:
-
nan
有毒,(5 *nan
=nan
) -
nan
不等于任何东西,甚至不等于本身(nan
!=nan
) -
nan
不大于(nan
!> 0) -
nan
不小于(nan
!<0)
列出的最后2个属性是反逻辑的,并且会导致依赖于与nan
数进行比较的代码的行为异常(最后3个属性也是奇数,但您可能永远不会在您的代码中看到x != x ?
代码(除非您正在(不可靠地)检查nan))。
在我自己的代码中,我注意到nan
值往往会产生难以发现的bug。 (注意:这是怎么不是的情况下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
之前不进行检查。
1 通过x != x
来检查nan
有时是不可靠的(某些优化编译器破坏了IEEE遵从性,特别是在启用-ffast-math
开关时, x != x
被剥离了)。
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3171749