为什么设置一个const变量(将以相同的值存储)导致一旦划分出不同的结果?

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.

如您所见,它会导致两种不同的结果.这让我很奇怪.

你能从技术上解释为什么会这样吗?

man*_*lio 7

"问题"是由于-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