关于计算机无法精确处理小数的问题
在之前练习JS的图片淡入淡出效果的时候我遇到过一个问题,我让opacity这个属性的值从0.3开始每次加0.1,然后当他到1的时候让他停止,然后发现,他居然到不了1!我当时把opacity的变化情况记录了下来:
0.4>0.5>0.6>0.7>0.799…>0.899…>0.99…>1.099…>0.99…>1.099…>0.99…
注意到0.7>0.7999…的部分,0.7+0.1=0.799999!?当时我就无语了,隐隐约约感觉到此事定有蹊跷。
<html>
<script type="text/javascript" >
window.onload =function(){
alert(0.4==0.40000000000000001);
}
</script>
</html>
试一下这段代码,各大浏览器大相近庭并且很神奇地弹了一个“true”给我,0.4=0.4……1?我测试了一下,从小数位后18位开始基本上所有小数都扑街了。
那么这个问题其实根本不是代码本身的问题,究其根本,计算机是以二进制的方式来存储数据,代码中的十进制小数,计算机都会替我们转换为二进制去进行计算。还记得十进制转换为二进制的手工方法吗——整数:“除二取余,逆序排列”、小数:“乘二取整,顺序排列”,随便找两个带小数点的数我们尝试一下:
15.43
整数部分:
15/2=7 余 1
7/2=3 余 1
3/2=1 余 1
1/2=0 余 1
除二取余,逆序排列:1111
小数部分:
0.43*2=0.86 整 0
0.86*2=1.72 整 1
0.72*2=1.44 整 1
0.44*2=0.88 整 0
0.88*2=1.76 整 1
0.76*2……
……
乘二取整,顺序排列:01101……
15.43二进制为:1111.01101……
再来一个
78.69
整数部分:
78/2=39 余 0
39/2=19 余 1
19/2=9 余 1
9/2=4 余 1
4/2=2 余 0
2/2=1 余 0
1/2=0 余 1
除二取余,逆序排列:1001110
小数部分:
0.69*2=1.38 整 1
0.38*2=0.76 整 0
0.76*2=1.52 整 1
0.52*2=1.04 整 1
0.04*2=0.08 整 0
0.08*2=0.16 整 0
0.16*2……
……
乘二取整,顺序排列:101100……
78.69的二进制为:1001110.101100……
可以发现,整数部分有一个2的0次方可以结束,但这个小数根本取不尽啊,回忆起来,当初学十进制二进制转换的时候,好像根本就没有人告诉我十进制小数转二进制这个过程什么时候可以停止。
实际上计算机的容量即使再大,他也是有限的,所以小数的计算,一定会出问题,唯一方法是,不要用小数,如果一定要用到,也要想办法将他转为整数再去计算。
上一篇: 用户积分功能
下一篇: 通过搜索引擎构建网站BI