mar*_*zzz 6 c++ floating-point optimization const
非常基本的代码:
#include <iostream>
int main() {
std::cout.precision(100);
double a = 9.79999999999063220457173883914947509765625;
double b = 0.057762265046662104872599030613855575211346149444580078125;
const double bConst = 0.057762265046662104872599030613855575211346149444580078125;
double c = a * b;
std::cout << " a: " << a << std::endl;
std::cout << " b: " << b << std::endl;
std::cout << " bConst: " << bConst << std::endl;
std::cout << " c: " << c << std::endl << std::endl;
std::cout << " c/b: " << c / b << std::endl;
std::cout << " c/bConst: " << c / bConst << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
哪个输出:
a: 9.79999999999063220457173883914947509765625
b: 0.057762265046662104872599030613855575211346149444580078125
bConst: 0.057762265046662104872599030613855575211346149444580078125
c: 0.5660701974567474703547986791818402707576751708984375
c/b: 9.7999999999906304282148994388990104198455810546875
c/bConst: 9.79999999999063220457173883914947509765625
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,b并且bConst似乎使用相同的值进行处理-即它打印两个相同的0.057762265046662104872599030613855575211346149444580078125值.所以我猜它们都是"存储"的.唯一的区别b是不是const.
然后,我做了c / b两次相同的操作:一次使用b,另一次使用bConst.
如您所见,它会导致两种不同的结果.这让我很奇怪.
你能从技术上解释为什么会这样吗?
"问题"是由于-freciprocal-math开关(暗示-Ofast):
如果允许优化,则允许使用值的倒数而不是除以值.例如,
x / y可以替换为x * (1/y),如果(1/y)受到共同的子表达式消除,这是有用的.请注意,这会丢失精度并增加对值进行操作的触发器数量.
编译器可以d = 1/bConst在编译时计算并从以下位置更改:
c/bConst
Run Code Online (Sandbox Code Playgroud)
至
c * d
Run Code Online (Sandbox Code Playgroud)
但乘法和除法是不同的指令,具有不同的性能和精度.
请参阅:http://coliru.stacked-crooked.com/a/ba9770ec39ec5ac2