当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《检查C++中的double(或float)是否为NaN》经验,为你挑选了12个好方法。

是否有isnan()函数?

PS.:我在MinGW(如果这有所不同).

我不得不用isnan()从此解决了,这是不存在的,这让我#include在第一荷兰国际集团.



1> jalf..:

根据IEEE标准,NaN值具有奇怪的特性,即涉及它们的比较总是错误的.也就是说,对于浮点f,只有当f是NaN时f != f才会成立.

请注意,正如下面的一些评论所指出的那样,并非所有编译器都在优化代码时尊重这一点.

对于声称使用IEEE浮点的任何编译器,这个技巧应该有效.但我不能保证它在实践中发挥作用.如果有疑问,请咨询您的编译器.


@Alf:`-ffast-math`选项的文档明确指出,如果IEEE或ISO规则/规范的数学函数,它可能导致程序的输出不正确,这取决于确切的实现.如果没有启用该选项,使用`x!= x`是一种完全有效且可移植的NaN测试方法.
-1只在理论上有效,而不是在实践中:g ++(带有-fastmath)之类的编译器搞砸了.直到c ++ 0x,唯一的通用方法是测试bitpattern.
@Alf:不,我不知道你和Gabriel Dos Reis的讨论.Steve Jessop在关于假设IEEE表示的另一个问题中提出了一个很好的观点.如果您假设IEEE 754并且编译器以一致的方式运行(即没有`-ffast-math`选项),那么`x!= x`是一个有效且可移植的解决方案.您甚至可以通过测试`__FAST_MATH__`宏来测试`-ffast-math`,并在这种情况下切换到不同的实现(例如使用联合和bit twiddling).
@Adam:文档确实公开声明它不符合,是的.是的,我之前遇到过这个论点,与Gabriel Dos Reis详细讨论过这个问题.它通常用来捍卫设计,在循环论证中(我不知道你是否打算与之相关联,但值得了解 - 这是火焰战争的东西).你的结论是`x!= x`在没有该选项的情况下是有效的,不符合逻辑.对于特定版本的g ++,它可能是真的.无论如何,您通常无法保证不会使用fastmath选项.
如果在IEEE模式下运行,编译器最好不要删除它.检查编译器的文档,当然......
使用xCode在`math.h`中包含的`isnan`实用程序,包括以下注释:_`-ffast-math`,其中包括暗示NaN不会发生,这允许编译器优化远离检查,如` x!= x`,这可能导致像`isnan(NaN)`这样的东西返回false.因此,如果使用`-ffast-math`进行编译,则会为这些实用程序生成_actual函数调用_._

2> mloskot..:

isnan()当前的C++标准库中没有可用的功能.它是在C99中引入的,定义为宏而不是函数.由C99定义的标准库的元素不是当前C++标准ISO/IEC 14882:1998的一部分,也不是其更新ISO/IEC 14882:2003.

2005年提出了技术报告1.TR1带来了与C99到C++的兼容性.尽管它从未被正式采用成为C++标准,但许多(GCC 4.0+或Visual C++ 9.0 + C++实现确实提供了TR1功能,所有这些功能或仅部分功能(Visual C++ 9.0不提供C99数学功能) .

如果TR1可用,则cmath包括C99元素,如isnan(),isfinite()等,但它们被定义为函数,而不是宏,通常在std::tr1::命名空间中,尽管许多实现(即Linux上的GCC 4+或Mac OS X 10.5+上的XCode)注入它们直接到std::,所以std::isnan定义明确.

此外,C++的一些实现仍然使C99 isnan()宏可用于C++(通过cmath或包含math.h),可能会导致更多混淆,开发人员可能会认为它是标准行为.

约Viusal C++的说明中,如上所述,它不提供std::isnan既不std::tr1::isnan,但它提供了定义为一个扩展函数_isnan()这一直是因为现有的Visual C++ 6.0

在XCode上,还有更多乐趣.如上所述,GCC 4+定义std::isnan.对于旧版本的编译器和库形式的XCode,似乎(这里是相关的讨论),没有机会检查自己)__inline_isnand()在Intel和__isnand()Power PC上定义了两个函数.


每个人都想要这些函数,如isNan或isInfinity.为什么负责人不仅仅是在他们的标准中? - 我会试着找出如何负责并投票支持.认真.
@Martin:它是C++ 11的一部分http://en.cppreference.com/w/cpp/numeric/math/isnan
这个答案应该更新,因为`std :: isnan`现在是C++ 11标准的一部分,支持已经扩散.std :: isnan是从Visual Studio 2013开始在Visual Studio中实现的.也许@shuhalo负责:-)
@shuhalo负责人呢?

3> BlueTrin..:
第一种解决方案:如果您使用的是C++ 11

由于这被要求有一些新的发展:重要的是要知道它std::isnan()是C++ 11的一部分

概要

在标题中定义

bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)

确定给定的浮点数arg是否不是-a-number(NaN).

参数

arg:浮点值

返回值

true如果arg是NaN,false否则

参考

http://en.cppreference.com/w/cpp/numeric/math/isnan

请注意,如果您使用g ++,这与-fast-math不兼容,请参阅下面的其他建议.


其他解决方案:如果您使用非C++ 11兼容工具

对于C99,在C中,这是作为isnan(c)返回int值的宏实现的.类型x应为float,double或long double.

各种供应商可能包含也可能不包含或不包含功能isnan().

要检查理应可移植的方法NaN是使用IEEE 754属性,NaN不等于本身:即x == x将是错误的xNaN.

但是最后一个选项可能不适用于每个编译器和一些设置(特别是优化设置),所以最后,你可以随时检查位模式......


绝对值得成为公认的答案,值得更多的赞成.谢谢你的提示
** - 1**`std :: isnan`仍然是2017年2月的推荐,因为它不适用于g ++的浮点优化.

4> Anonymous..:

Boost中还有一个只有头文件的库,它有很好的工具来处理浮点数据类型

#include 

您将获得以下功能:

template  bool isfinite(T z);
template  bool isinf(T t);
template  bool isnan(T t);
template  bool isnormal(T t);

如果你有时间看看Boost的整个Math工具包,它有许多有用的工具,而且发展很快.

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


如果使用选项--fast-math进行编译,则此函数将无法按预期工作.

5> Cheers and h..:

有三种"官方"方式:posix isnan,c ++ 0x isnan函数模板或visual c ++ _isnan函数.

不幸的是,检测哪些使用它是相当不切实际的.

不幸的是,没有可靠的方法来检测您是否使用带有NaN的IEEE 754表示.标准库提供官方这样的方式(numeric_limits::is_iec559).但在实践中,像g ++这样的编译器搞砸了.

从理论上讲,人们可以简单地使用x != x,但是像g ++和visual c ++这样的编译器可以搞砸了.

因此,最后,测试特定的NaN位模式,假设(并希望在某些时候执行!)特定表示,例如IEEE 754.


编辑:作为"g ++编译器的一个例子......搞砸了",考虑一下

#include 
#include 

void foo( double a, double b )
{
    assert( a != b );
}

int main()
{
    typedef std::numeric_limits Info;
    double const nan1 = Info::quiet_NaN();
    double const nan2 = Info::quiet_NaN();
    foo( nan1, nan2 );
}

用g ++编译(TDM-2 mingw32)4.4.1:

C:\test> type "C:\Program Files\@commands\gnuc.bat"
@rem -finput-charset=windows-1252
@g++ -O -pedantic -std=c++98 -Wall -Wwrite-strings %* -Wno-long-long

C:\test> gnuc x.cpp

C:\test> a && echo works... || echo !failed
works...

C:\test> gnuc x.cpp --fast-math

C:\test> a && echo works... || echo !failed
Assertion failed: a != b, file x.cpp, line 6

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
!failed

C:\test> _


@Adam:你缺少的是C++标准不需要IEEE表示或数学浮点数.至于手册页告诉你,`gcc -ffast-math`仍然是一个符合C++的实现(好吧,假设它得到`numeric_limits :: is_iec559`正确,它是,虽然Alf建议上面它没有):依赖于IEEE的C++代码不是*可移植的C++,并且没有权利期望实现提供它.
而Alf正确,快速测试gcc 4.3.4和`is_iec559`对于`-ffast-math`是正确的.所以这里的问题是GCC的`-ffast-math`文档只说它是非IEEE/ISO的数学函数,而它们*应该*说它是非C++,因为它的`numeric_limits`的实现是borked.我猜想GCC不能总是告诉模板定义的时候,最终的后端是否实际上有符合浮点数,所以甚至都没有尝试.IIRC在GCC的C99一致性的杰出错误列表中存在类似的问题.
@Alf:您的示例在Mac OS X和Linux上以4.0和4.5之间的各种版本的g ++工作,正如我所料.`-ffast-math`选项的文档明确指出,对于依赖于IEEE或ISO规则/规范的数学函数的精确实现的程序,它可能导致错误的输出.如果没有启用该选项,使用`x!= x`是一种完全有效且可移植的NaN测试方法.
@Eonil:C++ 0x仍然有例如"浮点类型的值表示是实现定义的".C和C++都旨在支持没有浮点硬件的机器上的实现,并且适当的IEEE 754浮点数可以比合理准确的替代方案慢一些.理论上,如果你需要IEEE,你可以断言`is_iec559`,在实践中似乎不适用于GCC.C++ 0x确实有一个`isnan`函数,但由于GCC现在没有正确实现`is_iec559`,我猜它也不会在C++ 0x中,并且`-ffast-math`可能会破坏它的` isnan`.

6> CTT..:

如果编译器支持c99扩展,则有一个std :: isnan,但我不确定mingw是否支持.

这是一个小函数,如果您的编译器没有标准函数,它应该可以工作:

bool custom_isnan(double var)
{
    volatile double d = var;
    return d != d;
}


如果设置了-ffast-math,则isnan()将无法返回gcc的正确结果.当然,这种优化被记录为破坏IEEE语义......
不,没有.执行该操作的编译器已损坏.你不妨说标准库`isnan`有可能返回错误的结果.从技术上讲,编译器*可能是错误的,但在实践中,不会发生.与`var!= var`相同.它的工作原理是因为这是定义IEEE浮点值的方式.
当这样做时,编译器有可能优化比较,总是返回true.
为什么不只是var!= var?

7> Bill the Liz..:

您可以使用标准库中numeric_limits::quiet_NaN( )定义的方法limits进行测试.有一个单独的常量定义double.

#include 
#include 
#include 

using namespace std;

int main( )
{
   cout << "The quiet NaN for type float is:  "
        << numeric_limits::quiet_NaN( )
        << endl;

   float f_nan = numeric_limits::quiet_NaN();

   if( isnan(f_nan) )
   {
       cout << "Float was Not a Number: " << f_nan << endl;
   }

   return 0;
}

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


但请注意 - GCC版本3.2.3中的numeric_limits中似乎存在错误,因为它返回0.0为quiet_NaN.根据我的经验,GCC的后期版本是可以的.

8> raimue..:

您可以使用该isnan()功能,但需要包含C数学库.

#include 

由于此功能是C99的一部分,因此无法在任何地方使用.如果您的供应商不提供该功能,您还可以定义自己的变体以实现兼容性.

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



9> bobobobo..:
预防

我对这个问题的回答是不要使用追溯检查nan.而是使用预防性检查表单的分部0.0/0.0.

#include 
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)

列出的最后两个属性是反逻辑的,并且会导致依赖于与nan数字进行比较的代码的奇怪行为(第三个最后一个属性也很奇怪,但您可能不会x != x ?在代码中看到(除非您正在检查对于nan(不可靠))).

在我自己的代码中,我注意到nan值往往会产生很难找到的错误.(请注意,或者不是这种情况.(<0)返回,(0 < )返回TRUE,偶数(< )返回TRUE.因此,根据我的经验,代码的行为通常仍然是所希望的.inf-inf-infTRUEinf-infinf

在南下做什么

你想要发生的事情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 检查nan通孔x != x有时是不可靠的(x != x被一些优化编译器剥离,违反IEEE合规性,特别-ffast-math是在启用开关时).


请注意,0.0/0.0不是唯一可能导致NaN的操作.负数的平方根返回NaN.+无穷大的余弦也会返回NaN.其中x不在[0,pi]范围内的操作acos(x)也可以导致NaN.简而言之,人们必须格外小心,也要注意这些潜在风险的操作,而不仅仅是0.0/0.0.

10> 小智..:

以下代码使用NAN的定义(所有指数位集,至少一个小数位集)并假设sizeof(int)= sizeof(float)= 4.您可以在维基百科中查找NAN以获取详细信息.

bool IsNan( float value ) { return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000; }



11> Cheers and h..:

从C++ 14开始,有许多方法可以测试浮点数value是否为NaN.

在这些方法中,只检查数字表示的位,可靠地工作,如我原来的答案中所述.特别是,std::isnan经常提出的检查v != v,不能可靠地工作,不应该使用,以免当某人决定需要浮点优化时,代码停止正常工作,并要求编译器执行此操作.这种情况可能会改变,编译器可以更加符合,但对于这个问题,自原始答案以来的6年内没有发生过.

大约6年来,我的原始答案是这个问题的选定解决方案,这是好的.但最近选择了推荐不可靠v != v测试的高度赞成的答案.因此,这个额外的更新的答案(我们现在有C++ 11和C++ 14标准,C++ 17即将出现).


从C++ 14开始,检查NaN-ness的主要方法是:

std::isnan(value) )
是自C++ 11以来的标准库.isnan显然与同名的Posix宏冲突,但在实践中这不是问题.主要问题是当请求浮点算术优化时,至少有一个主编译器,即g ++,std::isnan 返回falseNaN参数.

(fpclassify(value) == FP_NAN) )
遭受同样的问题std::isnan,即不可靠.

(value != value) )
在许多SO答案推荐.遭受同样的问题std::isnan,即不可靠.

(value == Fp_info::quiet_NaN()) )
这是一个测试,标准行为不应该检测NaN,但具有优化行为的可能会检测到NaN(由于优化的代码只是直接比较位级表示),并且可能与另一种方式相结合,以涵盖标准的未优化行为,可以可靠地检测NaN.不幸的是,事实证明它不可靠.

(ilogb(value) == FP_ILOGBNAN) )
遭受同样的问题std::isnan,即不可靠.

isunordered(1.2345, value) )
遭受同样的问题std::isnan,即不可靠.

is_ieee754_nan( value ) )
这不是标准功能.它根据IEEE 754标准检查位.它完全可靠,代码在某种程度上取决于系统.


在下面的完整测试代码中,"成功"是表达式是否报告值的Nan-ness.对于大多数表达式而言,这种成功度量,检测NaNs和仅NaNs的目标,对应于它们的标准语义.(value == Fp_info::quiet_NaN()) )但是,对于表达式,标准行为是它不能用作NaN检测器.

#include         // std::isnan, std::fpclassify
#include 
#include       // std::setw
#include 
#include      // CHAR_BIT
#include 
#include      // uint64_t
using namespace std;

#define TEST( x, expr, expected ) \
    [&](){ \
        const auto value = x; \
        const bool result = expr; \
        ostringstream stream; \
        stream << boolalpha << #x " = " << x << ", (" #expr ") = " << result; \
        cout \
            << setw( 60 ) << stream.str() << "  " \
            << (result == expected? "Success" : "FAILED") \
            << endl; \
    }()

#define TEST_ALL_VARIABLES( expression ) \
    TEST( v, expression, true ); \
    TEST( u, expression, false ); \
    TEST( w, expression, false )

using Fp_info = numeric_limits;

inline auto is_ieee754_nan( double const x )
    -> bool
{
    static constexpr bool   is_claimed_ieee754  = Fp_info::is_iec559;
    static constexpr int    n_bits_per_byte     = CHAR_BIT;
    using Byte = unsigned char;

    static_assert( is_claimed_ieee754, "!" );
    static_assert( n_bits_per_byte == 8, "!" );
    static_assert( sizeof( x ) == sizeof( uint64_t ), "!" );

    #ifdef _MSC_VER
        uint64_t const bits = reinterpret_cast( x );
    #else
        Byte bytes[sizeof(x)];
        memcpy( bytes, &x, sizeof( x ) );
        uint64_t int_value;
        memcpy( &int_value, bytes, sizeof( x ) );
        uint64_t const& bits = int_value;
    #endif

    static constexpr uint64_t   sign_mask       = 0x8000000000000000;
    static constexpr uint64_t   exp_mask        = 0x7FF0000000000000;
    static constexpr uint64_t   mantissa_mask   = 0x000FFFFFFFFFFFFF;

    (void) sign_mask;
    return (bits & exp_mask) == exp_mask and (bits & mantissa_mask) != 0;
}

auto main()
    -> int
{
    double const v = Fp_info::quiet_NaN();
    double const u = 3.14;
    double const w = Fp_info::infinity();

    cout << boolalpha << left;
    cout << "Compiler claims IEEE 754 = " << Fp_info::is_iec559 << endl;
    cout << endl;;
    TEST_ALL_VARIABLES( std::isnan(value) );                    cout << endl;
    TEST_ALL_VARIABLES( (fpclassify(value) == FP_NAN) );        cout << endl;
    TEST_ALL_VARIABLES( (value != value) );                     cout << endl;
    TEST_ALL_VARIABLES( (value == Fp_info::quiet_NaN()) );      cout << endl;
    TEST_ALL_VARIABLES( (ilogb(value) == FP_ILOGBNAN) );        cout << endl;
    TEST_ALL_VARIABLES( isunordered(1.2345, value) );           cout << endl;
    TEST_ALL_VARIABLES( is_ieee754_nan( value ) );
}

使用g ++的结果(再次注意,它的标准行为(value == Fp_info::quiet_NaN())是它不能用作NaN检测器,这只是非常实际的兴趣):

[C:\my\forums\so\282  (detect NaN)]
> g++ --version | find "++"
g++ (x86_64-win32-sjlj-rev1, Built by MinGW-W64 project) 6.3.0

[C:\my\forums\so\282  (detect NaN)]
> g++ foo.cpp && a
Compiler claims IEEE 754 = true

v = nan, (std::isnan(value)) = true                           Success
u = 3.14, (std::isnan(value)) = false                         Success
w = inf, (std::isnan(value)) = false                          Success

v = nan, ((fpclassify(value) == 0x0100)) = true               Success
u = 3.14, ((fpclassify(value) == 0x0100)) = false             Success
w = inf, ((fpclassify(value) == 0x0100)) = false              Success

v = nan, ((value != value)) = true                            Success
u = 3.14, ((value != value)) = false                          Success
w = inf, ((value != value)) = false                           Success

v = nan, ((value == Fp_info::quiet_NaN())) = false            FAILED
u = 3.14, ((value == Fp_info::quiet_NaN())) = false           Success
w = inf, ((value == Fp_info::quiet_NaN())) = false            Success

v = nan, ((ilogb(value) == ((int)0x80000000))) = true         Success
u = 3.14, ((ilogb(value) == ((int)0x80000000))) = false       Success
w = inf, ((ilogb(value) == ((int)0x80000000))) = false        Success

v = nan, (isunordered(1.2345, value)) = true                  Success
u = 3.14, (isunordered(1.2345, value)) = false                Success
w = inf, (isunordered(1.2345, value)) = false                 Success

v = nan, (is_ieee754_nan( value )) = true                     Success
u = 3.14, (is_ieee754_nan( value )) = false                   Success
w = inf, (is_ieee754_nan( value )) = false                    Success

[C:\my\forums\so\282  (detect NaN)]
> g++ foo.cpp -ffast-math && a
Compiler claims IEEE 754 = true

v = nan, (std::isnan(value)) = false                          FAILED
u = 3.14, (std::isnan(value)) = false                         Success
w = inf, (std::isnan(value)) = false                          Success

v = nan, ((fpclassify(value) == 0x0100)) = false              FAILED
u = 3.14, ((fpclassify(value) == 0x0100)) = false             Success
w = inf, ((fpclassify(value) == 0x0100)) = false              Success

v = nan, ((value != value)) = false                           FAILED
u = 3.14, ((value != value)) = false                          Success
w = inf, ((value != value)) = false                           Success

v = nan, ((value == Fp_info::quiet_NaN())) = true             Success
u = 3.14, ((value == Fp_info::quiet_NaN())) = true            FAILED
w = inf, ((value == Fp_info::quiet_NaN())) = true             FAILED

v = nan, ((ilogb(value) == ((int)0x80000000))) = true         Success
u = 3.14, ((ilogb(value) == ((int)0x80000000))) = false       Success
w = inf, ((ilogb(value) == ((int)0x80000000))) = false        Success

v = nan, (isunordered(1.2345, value)) = false                 FAILED
u = 3.14, (isunordered(1.2345, value)) = false                Success
w = inf, (isunordered(1.2345, value)) = false                 Success

v = nan, (is_ieee754_nan( value )) = true                     Success
u = 3.14, (is_ieee754_nan( value )) = false                   Success
w = inf, (is_ieee754_nan( value )) = false                    Success

[C:\my\forums\so\282  (detect NaN)]
> _

Visual C++的结果:

[C:\my\forums\so\282  (detect NaN)]
> cl /nologo- 2>&1 | find "++"
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23725 for x86

[C:\my\forums\so\282  (detect NaN)]
> cl foo.cpp /Feb && b
foo.cpp
Compiler claims IEEE 754 = true

v = nan, (std::isnan(value)) = true                           Success
u = 3.14, (std::isnan(value)) = false                         Success
w = inf, (std::isnan(value)) = false                          Success

v = nan, ((fpclassify(value) == 2)) = true                    Success
u = 3.14, ((fpclassify(value) == 2)) = false                  Success
w = inf, ((fpclassify(value) == 2)) = false                   Success

v = nan, ((value != value)) = true                            Success
u = 3.14, ((value != value)) = false                          Success
w = inf, ((value != value)) = false                           Success

v = nan, ((value == Fp_info::quiet_NaN())) = false            FAILED
u = 3.14, ((value == Fp_info::quiet_NaN())) = false           Success
w = inf, ((value == Fp_info::quiet_NaN())) = false            Success

v = nan, ((ilogb(value) == 0x7fffffff)) = true                Success
u = 3.14, ((ilogb(value) == 0x7fffffff)) = false              Success
w = inf, ((ilogb(value) == 0x7fffffff)) = true                FAILED

v = nan, (isunordered(1.2345, value)) = true                  Success
u = 3.14, (isunordered(1.2345, value)) = false                Success
w = inf, (isunordered(1.2345, value)) = false                 Success

v = nan, (is_ieee754_nan( value )) = true                     Success
u = 3.14, (is_ieee754_nan( value )) = false                   Success
w = inf, (is_ieee754_nan( value )) = false                    Success

[C:\my\forums\so\282  (detect NaN)]
> cl foo.cpp /Feb /fp:fast && b
foo.cpp
Compiler claims IEEE 754 = true

v = nan, (std::isnan(value)) = true                           Success
u = 3.14, (std::isnan(value)) = false                         Success
w = inf, (std::isnan(value)) = false                          Success

v = nan, ((fpclassify(value) == 2)) = true                    Success
u = 3.14, ((fpclassify(value) == 2)) = false                  Success
w = inf, ((fpclassify(value) == 2)) = false                   Success

v = nan, ((value != value)) = true                            Success
u = 3.14, ((value != value)) = false                          Success
w = inf, ((value != value)) = false                           Success

v = nan, ((value == Fp_info::quiet_NaN())) = false            FAILED
u = 3.14, ((value == Fp_info::quiet_NaN())) = false           Success
w = inf, ((value == Fp_info::quiet_NaN())) = false            Success

v = nan, ((ilogb(value) == 0x7fffffff)) = true                Success
u = 3.14, ((ilogb(value) == 0x7fffffff)) = false              Success
w = inf, ((ilogb(value) == 0x7fffffff)) = true                FAILED

v = nan, (isunordered(1.2345, value)) = true                  Success
u = 3.14, (isunordered(1.2345, value)) = false                Success
w = inf, (isunordered(1.2345, value)) = false                 Success

v = nan, (is_ieee754_nan( value )) = true                     Success
u = 3.14, (is_ieee754_nan( value )) = false                   Success
w = inf, (is_ieee754_nan( value )) = false                    Success

[C:\my\forums\so\282  (detect NaN)]
> _

总结上述结果,只使用is_ieee754_nan此测试程序中定义的函数直接测试位级表示,在所有情况下都可靠地使用g ++和Visual C++.


附录:
在发布上述内容后,我意识到还有另一种可能来测试NaN,在另一个答案中提到,即((value < 0) == (value >= 0)).事实证明,使用Visual C++可以正常工作,但是使用g ++的-ffast-math选项却失败了.只有直接位模式测试可靠地工作.









12> ST3..:
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.

在运行时间只是比较,铸件不需要任何时间.它只是更改比较标志配置以检查相等性.

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有