为什么计算机中 6 / 10 - 0.1 * 6 = -1.1102e-016?

请从原理上进行推导
另外请解释为什么 2 / 10 - 0.1 * 2 就会等于0
注C语言中 前面的 2 和 6 写成 2.0 和 6.0 不伤大雅

或者说在Matlab 以及任何编程语言中 为什么当 n / 10.0 - 0.1 * n 这个算式 当 n取 3 6 7 时并不等于0 这是为什么?
不信大家可以去试试
请通过计算机存储浮点数的原理进行推导。本人大概明白为什么 就好比0.1这个数用2进制表示是一个无限循环小数 所以存储时必定有截断误差,我大概只知道如何推到这个答案 但是太懒了 所以想请各位高手帮我推到下。

如果只知道0.1不能精确表示的话只能得到结果可能为零也可能非零,至于对于哪些n结果非零则需要更细致地分析舍入误差,偷懒是不行的

首先,fl(0.1)=0.1(1+t), 0<|t|<u, u=2^{-52}
但是仅知道这个还不够,要解释fl(6/10-0.1*6)=-u/2还需要知道t到底有多大影响
那么进一步,0.1=2^{-4}*(1.100110011001....)_2
除了第一位的1不显式保存以外,双精度浮点数能保存小数点后的52位,也就是
fl(0.1)=2^{-4}*(1.100110011001...10011010)_2
因为直接截断到52位后误差大于u/2,所以要进一位
把误差写成精确形式就是0.1t=2^{-4}*0.4*u,即t=u/4

接下来解释一下你观察到的现象
首先要知道浮点运算的结果fl(x@y)是离真实值x@y最近的浮点数,这里@可以是+,-,*,/,如果最近的浮点数有两个就舍入到偶
那么fl(n/10)就是n/10的浮点表示,但fl(fl(0.1)*n)=fl(0.1(1+t)*n)
所以一来要看n*t/10的影响有多大,二来还有f(n/10)本身的表示误差有多大

显然n=1,2,4,8,...的时候结果为0,因为n=2^k时fl(0.1*n)=fl(0.1)*n=fl(1/10)*n=fl(n/10)

对于n=3,fl(0.3)=2^{-2}*(1.00110011001...0011)_2=0.3-u/20
然而fl(0.1)*3=0.3(1+t)=0.3+3/40*u,已经知道0.3-u/20是一个浮点数,两者之差为u/8,恰好是u/4的一半
因此离fl(0.1)*3最近的浮点数有两个:0.3+3/40*u+u/8和0.3+3/40*u-u/8,根据舍入到偶的原则应取前者
所以fl(0.3)-fl(fl(0.1)*3)=-u/4
同理也解释了n=6时结果为-u/2

对于n=7,fl(0.7)=2^{-1}*(1.01100110010...0110)_2=0.7-u/5
fl(0.1)*7=0.7(1+t)=0.7+7/40*u,两者之差为3/8*u,大于u/2的一半,所以即使不分析是否有两个最接近的浮点数(当然这里只有一个,即0.7-u/5+u/2)也已知道结果非零

附赠n=5的情形,fl(0.5)没有误差,而fl(0.1)*5=0.5+u/8,误差小于u/2的一半,所以结果为0
温馨提示:内容为网友见解,仅供参考
第1个回答  2012-02-02
C语言中是区分数据类型的,比如2/10等于0,因为分子分母都是int型(整数型),最终结果也会将0.2转化成整型即为0!又如2.0/10等于0.2,因为如果分子分母数据类型不同,计算机会把两者数据类型统一为“大”的类型,这里10会转化为10.0,因此最终结果也是float型即为0.2!就是这个原因,你问题写的不是很明白,自己慢慢按这个方法琢磨吧!希望能帮到你!追问

可能是我表述的不好 你完全没有理解我的问题。
你可以试试 1 / 10 - 1 * 0.1 = 0 , 2 /10 - 2 * 0.1 = 0 , 3 / 10 - 3 * 0.1 不等于0 4 / 10 - 4 * 0.1 = 0, 5 / 10 - 5 * 0.1 = 0 , 6 / 10 - 0.1 * 6 不等于0 7 / 10 - 0.1 * 7 不等于0 8 / 10 - 8 * 0.1 =0 , 9 / 10 - 9 * 0.1 =0
你用就用Matlab和百度的计算器试试就行如果你不嫌麻烦你可以用任何编程语言试一试不过得输成1.0 / 10 - 1 * 0.1 的形式我想推倒为什么

第2个回答  2012-02-04
晕死了啊…
第3个回答  2012-02-03
我想是的追问

是什么?

追答

是楼上回答的

追问

现在问题不是这个 是这个结果是怎么出来的 我当然懂得这些数据结构在电脑中的存储方式了 也知道 整型下 2/10会等于0 楼上的回答说数据会转换类型 我当然是知道这个道理。我遇到的这个问题并不是由于数据类型转换而导致的 而是关乎计算机本质上二进制存储浮点数所存在的固有问题 我希望知道的是这个由于浮点数存储的局限性是如何导致上述算式在计算机中会得到如此的计算结果。

第4个回答  2012-02-02
追问

对不起 我表述的不太清楚 你可以看看我对楼下的追问 也许你就明白我想问什么了

追答

为什么计算机中 6 \/ 10 - 0.1 * 6 = -1.1102e-016?
那么fl(n\/10)就是n\/10的浮点表示,但fl(fl(0.1)*n)=fl(0.1(1+t)*n)所以一来要看n*t\/10的影响有多大,二来还有f(n\/10)本身的表示误差有多大 显然n=1,2,4,8,...的时候结果为0,因为n=2^k时fl(0.1*n)=fl(0.1)*n=fl(1\/10)*n=fl(n\/10)对于n=3,fl(0.3)=2^{-...

相似回答