检查double(或float)是否为C ++中的NaN

久未见 提交于 2020-02-27 22:54:25

有一个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是NaNfalse ,否则

参考

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对于xNaN将为假。

但是,最后一个选项可能不适用于每个编译器和某些设置(尤其是优化设置),因此,在万不得已时,您始终可以检查位模式...


#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.

nan0.f/0.f0.0/0.0运算0.f/0.fnan对您的代码的稳定性是一个可怕的宿敌,必须非常仔细地对其进行检测和预防 1nan与普通数不同的属性:

  • 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被剥离了)。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!