题
在编写一些测试用例时,一些测试检查了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 == NAN
是 true
, ,按原样 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家伙提出错误。