我知道,在大多数情况下,实数不能完全用二进制表示(即使是所谓的双精度)。例如,1/3近似于0x3FD55、55、55、55、55、55,实际上代表0×3333333333333333 1483…如果我们执行(1.0/3.0)+(1.0/3.0),那么我们得到0x3fe55555555555555(所以0.666666666666662965…),正如计算机算术意义上的预期。
但是,当我试图通过编写以下代码来执行(1.0/3.0)+(1.0/3.0)+(1.0/3.0)时
#include<stdio.h>
int main(){
double result=1.0/3.0;
result+=1.0/3.0;
result+=1.0/3.0;
printf("%016llx\n",result);
}
然后用标准GNU C编译器编译它,然后生成的程序返回0x3ff0000000000000(正好代表1)。这个结果让我很困惑,因为我最初期望0x3fefffffffffffffffff(我没想到舍入误差会互相抵消,因为(1.0/3.0)和((1.0/3.0)+(1.0/3.0))在用二进制表示时都小于实际值),我仍然没有弄清楚发生了什么。
如果你能告诉我这个结果的可能原因,我将不胜感激。
最佳答案
这是一个很好的四舍五入问题。如果我没记错的话,算术协处理器使用80位:64位精度,15位指数(ref.)。这意味着操作在内部使用的位比您可以显示的多。最后,协处理器实际循环其内部表示(更精确)以给出一个仅64位的值。由于第一个下降的位是1而不是0,所以结果是向上舍入,得到1。
但我必须承认我只是在猜测。。。
但是,如果您尝试手动执行该操作,则如果加法立即将所有精度位设置为1(加上5555…5和555…5移位1),再加上要删除的第一个位(也是1)。所以用手一个正常人也会向上舍入1,所以算术单位也能做正确的舍入也就不足为奇了。
关于c - 为什么三次添加1.0/3.0的效果与数学预期的一样?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48095871/