它提到当启用 fp:fast 模式时,诸如加法身份 (a±0.0 = a, 0.0-a = -a) 之类的操作是不安全的。
那篇文章说的是
当启用 fp:fast 模式时,优化器可以使用以下任何(不安全的)代数规则:
然后列出 a±0.0 = a 和 0.0-a = -a
并不是说启用 fp:fast 时这些身份是不安全的。就是说这些身份对于 IEEE 754 浮点算术来说是不正确的,但是 /fp:fast 将优化,就好像它们是真的一样。
我不确定是否有一个例子表明它a + 0.0 == a
是错误的(显然 NaN 除外),但 IEEE 754 有很多微妙之处,例如何时应该截断中间值。一种可能性是,如果您有一些包含 的表达式+ 0.0
,这可能会导致 IEEE 754 要求对中间值进行截断,但是 /fp:fast 将生成不进行截断的代码,因此会产生后续结果可能与 IEEE 754 严格要求的有所不同。
使用 Pascal Cuoq 的信息,这是一个基于 /fp:fast 产生不同输出的程序
#include <cmath>
#include <iostream>
int main() {
volatile double a = -0.0;
if (_copysign(1.0, a + 0.0) == _copysign(1.0, 0.0)) {
std::cout << "correct IEEE 754 results\n";
} else {
std::cout << "result not IEEE 754 conformant\n";
}
}
当使用 /fp:fast 构建时,程序会输出“结果不符合 IEEE 754”,而使用 /fp:strict 会导致程序输出“正确的 IEEE 754 结果”。