在编写一些测试用例时,一些测试检查了NAN的结果。

我尝试使用 std::isnan 但是断言失败了:

Assertion `std::isnan(x)' failed.

印刷后的价值之后 x, ,事实证明这是负面的(-nan)在我的情况下,这是完全可以接受的。

在尝试使用以下事实之后 NaN != NaN 并使用 assert(x == x), ,编译器对我有所帮助,并优化了断言。

做我自己的 isNaN 功能也正在优化。

我该如何检查NAN的两个平等 -Nan?

有帮助吗?

解决方案

这很尴尬。

编译器(在这种情况下为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 不安全。

其他提示

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

这看起来像图书馆的实现中的一个错误 isnan() 大部头书。它在Snow Leopard上的GCC 4.2.1上正常工作。但是,尝试这个呢?

std::isnan(std::abs(yourNanVariable));

显然,我无法测试,因为 std::isnan(-NaN)true 在我的系统上。

编辑: : 和 -ffast-math, ,不管 -O 开关,雪豹上的GCC 4.2.1认为 NAN == NANtrue, ,按原样 NAN == -NAN. 。这可能会灾难性地打破代码。我建议离开 -ffast-math 或至少测试使用而不是使用它的构建结果相同的结果...

您应该能够使用C99 isnan()。

如果在您的实现中,它无法正常工作(那是哪一个?),您可以通过将long并做ieee bit magic来实现自己的实现。

您可以检查数字的位。 IEEE 754已为Nan定义了面具:

  • 信号NAN由X'7F80 0001'和X'7FBF FFFF'或X'FF80 0001'和X'FFBF FFFF之间的任何位模式表示。
  • 安静的nan由x'7fc0 0000'和x'7fff ffff'或x'ffc0 0000'和x'ffff ffff'之间的任何位模式表示。

这可能是不可移植的,但是如果您确定自己的platfofm,则可以接受。更多的: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ib.ibm.xlf101l.doc/xlfopg/fpieee.htm

这是基于评论中发布的Wikipedia文章。请注意,它完全未经测试 - 它应该让您了解您可以做的事情。

bool reallyIsNan(float x)
{
    //Assumes sizeof(float) == sizeof(int)
    int intIzedX = *(reinterpret_cast<int *>(&x));
    int clearAllNonNanBits = intIzedX & 0x7F800000;
    return clearAllNonNanBits == 0x7F800000;
}

编辑:我真的认为您应该考虑向GLIBC家伙提出错误。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top