mar*_*zzz 6 c++ floating-point
我喜欢FP; 每次我想到它,我明白了解它:)
这是一个我不明白的例子.我总结8次相同的数字(0.1),我打印结果,总和和"原始":
std::cout.precision(100);
int numIteration = 8;
double step = 0.1;
double sum = 0.0;
for(int i = 0; i < numIteration; i++) {
sum += step;
}
std::cout << "orig stored as " << numIteration / 10.0 << std::endl;
std::cout << " sum stored as " << sum << std::endl;
Run Code Online (Sandbox Code Playgroud)
0.1存储为0.1000000000000000055511151231257827021181583404541015625,我希望在8和之后,它将被存储大于或等于0.8,存储为0.8000000000000000444089209850062616169452667236328125.
但结果震惊了我.实际上经过8次求和后,结果0.79999999999999993338661852249060757458209991455078125就越小.
另外,如果我检查两者的二进制输出,我可以看到总和比"原始"更"高":
0.8 stored as binary 0 01111111110 1001100110011001100110011001100110011001100110011001 // smaller
sum stored as binary 0 01111111110 1001100110011001100110011001100110011001100110011010 // higher
Run Code Online (Sandbox Code Playgroud)
但是0.79999999999999993338661852249060757458209991455078125< 0.8000000000000000444089209850062616169452667236328125.
你能照我吗?
编辑:对不起,我复制/粘贴二进制文件时出错.他们是对的.
随着IEEE浮点舍入每个运算后会发生.四舍五入可能会上升或下降.如果您sum在每次迭代时打印值,您应该看到:
sum is 0.1000000000000000055511151231257827021181583404541015625
sum is 0.200000000000000011102230246251565404236316680908203125
sum is 0.3000000000000000444089209850062616169452667236328125
sum is 0.40000000000000002220446049250313080847263336181640625
sum is 0.5
sum is 0.59999999999999997779553950749686919152736663818359375
sum is 0.6999999999999999555910790149937383830547332763671875
sum is 0.79999999999999993338661852249060757458209991455078125
Run Code Online (Sandbox Code Playgroud)
你假设四舍五入只能上升.但是,由于"Round to nearest,ties to even"是IEEE 754中的默认舍入模式,因此在每次迭代时都会选择最接近的二进制可表示值,因此结果不必大于0.8.
另一方面
std::cout << 0.1 * 8.0 << std::endl;
Run Code Online (Sandbox Code Playgroud)
会产生预期的
0.8000000000000000444089209850062616169452667236328125
Run Code Online (Sandbox Code Playgroud)
更新:如注释中提到的@Evg,可以更改浮点舍入方向std::fesetround.
| 归档时间: |
|
| 查看次数: |
196 次 |
| 最近记录: |