401

有 isnan() 函数吗?

PS.:我在MinGW(如果这有什么不同的话)。

我通过使用 isnan() from 解决了这个问题<math.h>,它在 中不存在<cmath>,我一开始是在#includeing 中。

4

20 回答 20

383

根据 IEEE 标准,NaN 值具有奇数特性,即涉及它们的比较总是错误的。也就是说,对于浮点数 f,当 f 为 NaN时才f != f为真。

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

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

于 2009-02-20T18:17:35.987 回答
228

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

2005 年提出了技术报告 1。TR1 为 C++ 带来了与 C99 的兼容性。尽管事实上它从未被正式采用成为 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++ 的一些实现仍然使 C99isnan()宏可用于 C++(通过cmathor包含math.h),这可能会导致更多的混淆,开发人员可能会认为这是一种标准行为。

关于 Viusal C++ 的注释,如上所述,它std::isnan既不提供std::tr1::isnan,但提供了定义为自Visual C++ 6.0_isnan()以来可用的扩展函数

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

于 2010-01-23T16:19:05.740 回答
208

第一个解决方案:如果您使用的是 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 中,这被实现为isnan(c)返回 int 值的宏。的类型x应为浮点型、双精度型或长双精度型。

不同的供应商可能包含也可能不包含或不包含某个功能isnan()

据称可移植的检查方法是使用不等于自身NaN的 IEEE 754 属性:即 ie将是false 。NaNx == xxNaN

但是,最后一个选项可能不适用于每个编译器和某些设置(特别是优化设置),因此在最后的手段中,您始终可以检查位模式......

于 2013-05-30T13:30:09.487 回答
81

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 的整个数学工具包,它有许多有用的工具并且正在快速增长。

此外,在处理浮点数和非浮点数时,查看Numeric Conversions可能是个好主意。

于 2009-02-20T20:40:03.117 回答
44

共有三种“官方”方式:posixisnan、c++0xisnan函数模板或可视化 c++_isnan函数

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

不幸的是,没有可靠的方法来检测您是否具有带有 NaN 的 IEEE 754 表示。标准库提供了官方的这种方式(numeric_limits<double>::is_iec559)。但在实践中,诸如 g++ 之类的编译器搞砸了。

理论上可以简单地使用x != x,但是像 g++ 和 visual c++ 这样的编译器会把它搞砸。

所以最后,测试特定的NaN 位模式,假设(并希望在某个时候强制执行!)特定的表示,例如 IEEE 754。


编辑:作为“诸如 g++ 之类的编译器……搞砸”的一个例子,考虑

#include <limits>
#include <assert.h>

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

int main()
{
    typedef std::numeric_limits<double> 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> 键入“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> 一个 && 回声工作... || 回声!失败
作品...

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

C:\test> 一个 && 回声工作... || 回声!失败
断言失败:a != b,文件 x.cpp,第 6 行

此应用程序已请求运行时以不寻常的方式终止它。
请联系应用程序的支持团队以获取更多信息。
!失败的

C:\测试> _
于 2011-03-26T09:08:46.197 回答
39

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

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

bool custom_isnan(double var)
{
    volatile double d = var;
    return d != d;
}
于 2009-02-20T18:14:58.817 回答
25

您可以使用标准库中numeric_limits<float>::quiet_NaN( )定义的limits来进行测试。为 定义了一个单独的常量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++ 进行了测试。

于 2009-02-20T19:18:12.580 回答
21

您可以使用该isnan()函数,但您需要包含 C 数学库。

#include <cmath>

由于此功能是 C99 的一部分,因此并非随处可用。如果您的供应商不提供该功能,您也可以定义自己的变体以实现兼容性。

inline bool isnan(double x) {
    return x != x;
}
于 2009-02-20T18:18:31.837 回答
13

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

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

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


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

  • 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。对于大多数表达式,这种衡量成功的方法、检测 NaN 和仅检测 NaN 的目标对应于它们的标准语义。然而,对于(value == Fp_info::quiet_NaN()) )表达式,标准行为是它不能用作 NaN 检测器。

#include <cmath>        // std::isnan, std::fpclassify
#include <iostream>
#include <iomanip>      // std::setw
#include <limits>
#include <limits.h>     // CHAR_BIT
#include <sstream>
#include <stdint.h>     // 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<double>;

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<uint64_t const&>( 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(检测 NaN)]
> g++ --版本 | 找到“++”
g++ (x86_64-win32-sjlj-rev1, 由 MinGW-W64 项目构建) 6.3.0

[C:\my\forums\so\282(检测 NaN)]
> g++ foo.cpp && a
编译器声称 IEEE 754 = true

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

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

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

v = nan, ((value == Fp_info::quiet_NaN())) = false 失败
u = 3.14, ((value == Fp_info::quiet_NaN())) = false 成功
w = inf, ((value == Fp_info::quiet_NaN())) = false 成功

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

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

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

[C:\my\forums\so\282(检测 NaN)]
> g++ foo.cpp -ffast-math && a
编译器声称 IEEE 754 = true

v = nan, (std::isnan(value)) = false 失败
u = 3.14, (std::isnan(value)) = false 成功
w = inf, (std::isnan(value)) = false 成功

v = nan, ((fpclassify(value) == 0x0100)) = false 失败
u = 3.14, ((fpclassify(value) == 0x0100)) = false 成功
w = inf, ((fpclassify(value) == 0x0100)) = false 成功

v = nan, ((value != value)) = false 失败
u = 3.14, ((value != value)) = false 成功
w = inf, ((value != value)) = false 成功

v = nan, ((value == Fp_info::quiet_NaN())) = true 成功
u = 3.14, ((value == Fp_info::quiet_NaN())) = true 失败
w = inf, ((value == Fp_info::quiet_NaN())) = true 失败

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

v = nan, (isunordered(1.2345, value)) = false 失败
u = 3.14, (isunordered(1.2345, value)) = false 成功
w = inf, (isunordered(1.2345, value)) = false 成功

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

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

Visual C++ 的结果:

[C:\my\forums\so\282(检测 NaN)]
> cl /nologo- 2>&1 | 找到“++”
Microsoft (R) C/C++ 优化编译器版本 19.00.23725 for x86

[C:\my\forums\so\282(检测 NaN)]
> cl foo.cpp /Feb && b
foo.cpp
编译器声称 IEEE 754 = true

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

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

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

v = nan, ((value == Fp_info::quiet_NaN())) = false 失败
u = 3.14, ((value == Fp_info::quiet_NaN())) = false 成功
w = inf, ((value == Fp_info::quiet_NaN())) = false 成功

v = nan, ((ilogb(value) == 0x7fffffff)) = true 成功
u = 3.14, ((ilogb(value) == 0x7fffffff)) = false 成功
w = inf, ((ilogb(value) == 0x7fffffff)) = true 失败

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

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

[C:\my\forums\so\282(检测 NaN)]
> cl foo.cpp /Feb /fp:fast && b
foo.cpp
编译器声称 IEEE 754 = true

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

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

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

v = nan, ((value == Fp_info::quiet_NaN())) = false 失败
u = 3.14, ((value == Fp_info::quiet_NaN())) = false 成功
w = inf, ((value == Fp_info::quiet_NaN())) = false 成功

v = nan, ((ilogb(value) == 0x7fffffff)) = true 成功
u = 3.14, ((ilogb(value) == 0x7fffffff)) = false 成功
w = inf, ((ilogb(value) == 0x7fffffff)) = true 失败

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

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

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

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


附录:
在发布上述内容后,我意识到另一种可能测试 NaN 的方法,在此处的另一个答案中提到,即((value < 0) == (value >= 0)). 事实证明,这在 Visual C++ 上工作得很好,但在 g++ 的-ffast-math选项下失败了。只有直接位模式测试才能可靠地工作。

于 2017-02-09T13:49:12.287 回答
12

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

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

于 2011-04-05T01:53:33.510 回答
12

楠预防

我对这个问题的回答是不要对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.0nan是代码稳定性的可怕克星,必须非常小心地检测和防止1 . 其性质nan与普通数不同:

  • nan有毒,(5* nan= nan)
  • nan不等于任何东西,甚至不等于自身 ( nan!= nan)
  • nan不大于任何东西(nan!> 0)
  • nan不小于任何东西 ( nan!< 0)

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

在我自己的代码中,我注意到nan值往往会产生难以发现的错误。(请注意,对于or而言,情况并非如此。 ( < 0) 返回, ( 0 < ) 返回 TRUE,甚至 ( < ) 返回 TRUE。因此,根据我的经验,代码的行为通常仍符合预期)。inf-inf-infTRUEinf-infinf

在nan下做什么

你想要发生的事情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.finf将导致(实际上如上所述,它具有非常好的/非破坏性行为)。

请记住,整数除以 0 会导致运行时异常。因此,您必须始终检查整数除以 0。仅仅因为0.0/0.0悄悄地评估为nan并不意味着您可以懒惰并且0.0/0.0在它发生之前不检查。

1检查nanviax != x有时是不可靠的(x != x被一些破坏 IEEE 合规性的优化编译器剥离,特别-ffast-math是在启用开关时)。

于 2013-08-16T22:41:23.033 回答
7
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,则此方法有效。

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

于 2013-10-03T10:32:12.343 回答
4

不依赖于所用 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) );
}
于 2012-04-03T22:03:16.073 回答
4

考虑到 NaN 并不总是保证 (x != x) (例如,如果使用 -ffast-math 选项),我一直在使用:

#define IS_NAN(x) (((x) < 0) == ((x) >= 0))

数字不能同时为 < 0 和 >= 0,所以实际上只有当数字既不小于、也不大于或等于零时,此检查才会通过。这基本上根本就不是数字,或者是 NaN。

如果您愿意,也可以使用它:

#define IS_NAN(x) (!((x)<0) && !((x)>=0)

我不确定这如何受到 -ffast-math 的影响,因此您的里程可能会有所不同。

于 2016-01-26T01:06:53.473 回答
3

至于我,解决方案可能是一个宏,使其显式内联,因此速度足够快。它也适用于任何浮点类型。它基于这样一个事实,即值不等于自身的唯一情况是值不是数字时。

#ifndef isnan
  #define isnan(a) (a != a)
#endif
于 2012-12-11T09:08:56.793 回答
3

这有效:

#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;
}

输出:伊斯南

于 2014-08-03T22:38:29.977 回答
1

在我看来,最好的真正跨平台方法是使用联合并测试双精度的位模式以检查 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;
}
于 2016-10-08T17:20:07.160 回答
-1

IEEE 标准规定,当指数全为1s 且尾数不为零时,数字为 a NaN。Double 是1符号位、11指数位和52尾数位。做一点检查。

于 2014-01-31T19:26:31.673 回答
-3

正如上面的评论所说 a != 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”)

于 2013-06-26T21:33:59.863 回答
-3

这通过检查它是否在双重限制内来检测 Visual Studio 中的无穷大和 NaN:

//#include <float.h>
double x, y = -1.1; x = sqrt(y);
if (x >= DBL_MIN && x <= DBL_MAX )
    cout << "DETECTOR-2 of errors FAILS" << endl;
else
    cout << "DETECTOR-2 of errors OK" << endl;
于 2018-11-30T08:45:36.507 回答