负NaN不是NaN?

Lir*_*una 29 c++ nan fast-math

在编写一些测试用例时,有些测试会检查NaN的结果.

我尝试使用std::isnan但断言错误:

Assertion `std::isnan(x)' failed.
Run Code Online (Sandbox Code Playgroud)

打印出值后x,结果显示它是负NaN(-nan),在我的情况下是完全可以接受的.

在尝试使用NaN != NaN和使用的事实之后assert(x == x),编译器给我一个'恩惠'并优化断言.

制作我自己的isNaN功能也正在优化.

如何检查NaN -NaN的相等性?

Lir*_*una 33

这很尴尬.

编译器(在这种情况下是GCC)优化远离比较并isnan返回的false原因是因为我团队中的某个人已经打开了-ffast-math.

来自文档:

-ffast-math
    Sets -fno-math-errno, -funsafe-math-optimizations,
    -fno-trapping-math, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans and fcx-limited-range.

    This option causes the preprocessor macro __FAST_MATH__ to be defined.

    This option should never be turned on by any -O option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions. 

注意结束语 - -ffast-math不安全.

  • 当与 /fp:fast 标志一起使用时,我刚刚注意到 MS 编译器存在完全相同的问题。与 /fp:precise 一起工作正常。 (2认同)

sam*_*var 5

isnan()预计会有未定义的行为-ffast-math

这是我在测试套件中使用的:

#if defined __FAST_MATH__
#   undef isnan
#endif
#if !defined isnan
#   define isnan isnan
#   include <stdint.h>
static inline int isnan(float f)
{
    union { float f; uint32_t x; } u = { f };
    return (u.x << 1) > 0xff000000u;
}
#endif
Run Code Online (Sandbox Code Playgroud)