【发布时间】:2014-05-20 19:14:18
【问题描述】:
示例代码:
#include <iostream>
#include <cmath>
#include <stdint.h>
using namespace std;
static bool my_isnan(double val) {
union { double f; uint64_t x; } u = { val };
return (u.x << 1) > (0x7ff0000000000000u << 1);
}
int main() {
cout << std::isinf(std::log(0.0)) << endl;
cout << std::isnan(std::sqrt(-1.0)) << endl;
cout << my_isnan(std::sqrt(-1.0)) << endl;
cout << __isnan(std::sqrt(-1.0)) << endl;
return 0;
}
使用-ffast-math,该代码打印“0, 0, 1, 1” - 没有,它打印“1, 1, 1, 1”。
正确吗?我认为std::isinf/std::isnan 在这些情况下仍应与-ffast-math 一起使用。
另外,如何使用-ffast-math 检查无穷大/NaN?您可以看到 my_isnan 这样做,它确实有效,但该解决方案当然非常依赖于架构。另外,为什么my_isnan 在这里工作而std::isnan 不工作? __isnan 和 __isinf 怎么样。它们总是有效吗?
对于-ffast-math,std::sqrt(-1.0) 和std::log(0.0) 的结果是什么。它是未定义的,还是应该是 NaN / -Inf?
相关讨论:(GCC) [Bug libstdc++/50724] New: isnan broken by -ffinite-math-only in g++、(Mozilla) Bug 416287 - performance improvement opportunity with isNaN
【问题讨论】:
-
我认为这取决于您使用的编译器和操作系统。在 OS X 上使用
clang5.1,您的示例代码将打印1。 -
@SylvainDefresne:是的,但问题主要是:如何以始终有效的方式进行检查?
-
打印
std::log(0.0)以查看std::log或std::isinf是否计算出错误的结果可能会有所帮助。 -
您的 my_isnan 不正确:
my_isnan(45.0) == 1 -
@Jean-MichaëlCelerier 那是什么硬件?我猜
my_isnan仅适用于 x86-64 左右。
标签: c++ c++-standard-library fast-math