JavaScript中0.1+0.2 为什么不等于0.3

330 阅读2分钟

0.1+0.2运算时发生了什么?

首先,计算机无法直接对十进制的数字进行运算,需要转换成二进制。

这样运算就分成了两部分:

1.先按照 IEEE 754 转成相应的二进制
2.进行对阶运算

浮点数必须通过二进制来进行计算,必须遵循 IEEE 754 标准 通过64位来表示一个数字

通过图片具体看一下数值在内存中的表示

图片文字说明

第0位:符号位,0表示正数,1表示负数(s)

第1位到第11位:储存指数部分(e)

第12位到第63位:储存小数部分(即有效数字)f

1.进制转换

0.1 和 0.2 转换成二进制后会无限循环

0.1 -> 0.0001100110011001100110011001100110011001100110011001101....(无限循环)
0.2 -> 0.001100110011001100110011001100110011001100110011001101...(无限循环)

但是由于 IEEE 754 尾数位数限制,IEEE754标准规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。只有32位模式有强制要求,其他都是选择性的。

这样在进制转换之后,就已近产生第一次精度丢失

2.对阶运算

由于指数位数不相同,运算时需要对阶运算也会产生精度损失

按照上面两步运算后的结果是

0.0100110011001100110011001100110011001100110011001101....(无限循环)

结果转换成十进制之后就是 0.30000000000000004

经过两步操作后,会产生两次精度丢失,所以浏览器显示的结果就就会显示不等

本文参考文章

wikipedia-IEEE 754

漫谈计算机组成原理(十)浮点数运算

0.1 + 0.2不等于0.3?为什么JavaScript有这种“骚”操作?

十进制的0.1 为什么不能用二进制很好的表示?