js浮点数精度问题

934 阅读2分钟

导读

经常会看到这样个问题,为什么0.1+0.2不等于0.3呢?是怎么形成的呢?

  • 我们知道计算机冲存储的都是二进制,而我们js这份语言中,所有的数字都统一用双精度浮点型(double)表示,总共占用8个字节。因为双精度浮点型,所以js中所有Number类型的数据都需要转换为二进制小数,再用科学计数法(a×10^b)表示。

科学计数法在计算机中存储的结构

总共8个字节总共64位,那怎么使用这64位呢?

  • 符号位:1位(1表示正数,0表示负数)
  • 指数位:11位
  • 小数位:52位

换算和存储的过程

  • 1:十进制小数转换为二进制。(www.runoob.com/w3cnote/dec…
  • 2:得到二进制小数后,转换为科学计数法(a×10^b)表示。(www.ruanyifeng.com/blog/2010/0…
  • 2.1:根据小数的正负得到符号位
  • 2.2:根据换算结果得到e,e + 偏移量(Math.pow(2, 11) - 1)等于指数位。偏移量是固定的11位,所有也就是2的11次方减1.
  • 3:若二进制小数长度大于五十二位,则进行二进制的四舍五入(遇0舍,遇1入),若二进制小数长度小于52位,则后面补0直到长度达到52位

上面的换算的第三部中其实是会存在问题的,是上面问题呢?

  • 当一个小数转换为二进制小数后,是一个无理数呢。或者和我们的圆周率π一样呢。我们计算机存储就遇到问题了。所以就有了上述第三步中的二进制四舍五入。这也就是js中0.1 + 0.2 大于0.3的原因。
其实也不是js存在这个问题,出现这个问题的原因还是和计算机底层的二进制存储有关,二进制可以准确地表示每一个整数,但是浮点数就不一定了。