我对利用C++实现浮点乘倍的精度有一些疑问。
当我尝试下面的代码时,
#include <iostream>
using namespace std;
int main() {
double x = 288144;
float lr = 0.1;
printf("value of lr*x = %lf \n", lr*x);
printf("value of x*lr = %lf \n", x*lr);
for (int i = 0; i<1000; ++i) {
x = x*lr + x*(1-lr);
printf("epoch %d, value of x*lr = %lf \n", i, x*lr);
printf("epoch %d, value of x*(1-lr) = %lf \n", i, x*(1-lr));
printf("epoch %d, value of x = %lf \n", i, x);
}
return 0;
}给出的结果
value of lr*x = 28814.400429
value of x*lr = 28814.400429
epoch 0, value of x*lr = 28814.399785
epoch 0, value of x*(1-lr) = 259329.587334
epoch 0, value of x = 288143.993559
epoch 1, value of x*lr = 28814.399141
epoch 1, value of x*(1-lr) = 259329.581537
epoch 1, value of x = 288143.987119
epoch 2, value of x*lr = 28814.398497
epoch 2, value of x*(1-lr) = 259329.575741
epoch 2, value of x = 288143.980678
...
epoch 998, value of x*lr = 28813.757029
epoch 998, value of x*(1-lr) = 259323.802523
epoch 998, value of x = 288137.565992
epoch 999, value of x*lr = 28813.756385
epoch 999, value of x*(1-lr) = 259323.796727
epoch 999, value of x = 288137.559552 正如我们所看到的,在循环之外,lr*x大于28814,内部更低。那么,为什么x = x*lr + x*(1-lr)在循环和循环之后会减少呢?另外,如果将float lr = 0.1;的代码转换为double lr = 0.1,则xlr + x(1-lr)的结果总是等于x。
发布于 2022-01-10 10:34:37
因此,当double与float相乘时,首先将float参数提升为双倍,然后执行乘法。现在在您的代码中有一个片段
x * (1 - lr)在这种情况下,计算1-lr,使1被提升为float,然后执行减法。然后,将结果提升到double,以便与x相乘。(实际上,如果您查看生成的汇编程序代码,至少在我使用GCC 9.3的系统中,1-lr是在编译时计算的,因为它是一个编译时常量。)
至于为什么x*lr在循环外更大而内部更小的问题,这是因为您在更新x之后打印了迭代0的结果。
https://stackoverflow.com/questions/70650640
复制相似问题