平日里喜欢用电脑上安装的python自带IDLE当计算器使用,今天下午在学习乘法节点传播的时候用它计算了450*1.1等于多少。结果本该是一个整数,但是打印出来的结果让我有点不知所措,好像记得学校老师讲过浮点运算问题,不过忘了。
>>> 450*1.1
495.00000000000006
于是赶紧把书放下,去网上搜一下原有。有人说是奖励你比较勤奋,也有人说是脚本语言的缺陷。然后我试了一下java的jdk8版本也是这种情况,只能说这网友瞎说。
后来我试了一下其他的数字:
>>> for i in range(10):
print((i+1)*100*1.1)
110.00000000000001
220.00000000000003
330.0
440.00000000000006
550.0
660.0
770.0000000000001
880.0000000000001
990.0000000000001
1100.0
在网上看见有人解释到了二级制我就知道应该是这个问题,十进制下的1.1转成二进制是没有明确的数值的。依据转换规则得到的二进制是一个无限小数。这就解释了为什么450*1.1得到的浮点数后面有个不该有的6,这是因为计算在四舍五入导致的。
0.1 => 0.0001 1001 1001 1001…(无限循环)
在300、500、600、1000乘于1.1的时候这没有出现这种情况。是因为有些时候转化正好不是无限循环小数,或者是因为误差极小,在计算机显示的时候舍入(计算机显示的时候也要舍入,一般内部运算位数大于显示位数)掉了,这种小概率事件用的时间长了,哪种语言都会出现这种情况。除非有一种语言,运算位数和显示位数差距过大,这种误差总是在显示的时候被舍掉。
除了上面乘法还有一些加法操作:
0.1+0.2=0.30000000000000004
因此在做浮点型计算时,一定要保留一定的小数点位数,避免计算机内部在做四舍五入操作时发生结果上的缺陷。