在看js 的过程中发现了0.1加0.2不等于0.3,查了半天资料,总结一下免得忘记了…
可以阅读英文原文参考资料:参考资料
这个问题不仅仅存在于js,其他很多语言也有这个问题,这是使用基于IEEE754 数值的浮点计算的通病。
1.小数在计算机中的表示
首先,小数在计算机中按照二进制保存,如 0.5 表示为 0.1(2的-1次方) ,0.125表示为 0.001 (2 的 -3次方)。但是小数如果不是这些可以被2的负多少次方表示的数,那么二进制可能无法在有限位精确表示。
如0.1(十进制)表示为二进制就是:0.0001100110011001…
在IEEE754浮点数中,分为双精度和单精度两种类型,单精度32个比特存储,双精度浮点数64个比特存储。
这里讨论双精度小数。双精度小数64位按照科学计数法来保存小数。
由以下三部分组成(Sign:符号位 Exponent:指数位 Mantissa:尾数位)
Sign 符号位:
表示正负
Exponent 指数位:
数字的含义我的理解是 2的次方数。如指数位算出来是4就是二进制的2次方,是8就是二进制的三次方。
这里应该有11位,多一个指数位的符号位。所以二进制的-2次方指数位表示为 01111111011.
Mantissa尾数位:
保存的二进制数字,默认科学计数法第一个有效数字必定是1,因此这个1不储存。最大保存52位。
2. 0.1在计算机中的表示
0.1的二进制计算方式如下:
将每次乘2的整数位记录下来即0.1的二进制表示,计算如下:
那么写成科学计数法,表示如下:
指数位计算按照刚才所写,计算为:01111111011.
所以 64位 的 0.1 表示为:[符号位][尾数位][指数位]:
同理 0.2等于:
加起来等于:
转换为十进制则为0.30000000000000004.