Skip to content
Published:

关于 0.1 + 0.2 !== 0.3 的问题, 迄今为止最满意的一次回答

0.1+0.2
0.30000000000000004

??? why ???

其实关于这个问题,网上的解释很多,归根到底,普遍都在甩锅给 js 精度缺失位数溢出 等等…也确实不能说不对,但一直觉得没解释到点上,例如

那我们来深入的解释下 为什么 0.1 + 0.2 !== 0.3

Table of contents

Open Table of contents

计算的本质是 二进制 进行的

我们知道 十进制转化为 二进制的过程是辗转相乘,且

8 / 2 = 4 余 0
4 / 2 = 2 余 0
2 / 2 = 1 余 0
1 / 2 = 0 余 1

8 => 1000
0.1 * 2 = 0.2 取整 0
0.2 * 2 = 0.4 取整 0
0.4 * 2 = 0.8 取整 0
0.8 * 2 = 1.6 取整 1
0.6 * 2 = 1.2 取整 1
0.2 * 2 = 0.4 取整 0
0.4 * 2 = 0.8 取整 0
0.8 * 2 = 1.6 取整 1
0.6 * 2 = 1.2 取整 1
......
0.1 => 00011 0011 0011 0011 .... (0011 循环)

Number (js) 类型是使用 IEEE754 标准 64 位存储 (double, 双精度浮点数)

系统为每个 num 分配 64 位存储空间,以科学技术法存储 1.xxx * 2^n。

而 64 位存储空间分为三个部分

举个栗子

0.1 转化为科学计数法:0.1 = 0.00011 0011 0011 0011 .... = 1.1001 1001... * 2^(-4)

这里发生了第一次精度丢失! 存储过程中丢失

0.1 = 0 01111111011 1001100110011001100110011001100110011001100110011010

0.2 = 0 01111111100 1001100110011001100110011001100110011001100110011010

IEEE754 标准 64 位 数值相加

0.1 偏移 -4:0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010

0.2 偏移 -3:0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0100

相加得到 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 111 (53 位)

截取保留 52 位 0.010011001100110011001100110011001100110011001100110100 (52位)

这里发生了第二次精度丢失! 相加过程中丢失

转化为 10 进制 0.30000000000000004