美文网首页前端知识点
js浮点数精度计算问题

js浮点数精度计算问题

作者: AmazRan | 来源:发表于2019-10-20 17:23 被阅读0次

前言

项目中,总是不可避免会出现js的浮点数精度计算问题。
抛出经典问题:为什么0.1===0.10.1+0.2!==0.3


出现问题的原因

根源要追溯到JavaScript的浮点数的存储上。和其它语言如Java和Python不同,JavaScript中所有数字包括整数和小数都只有一种类型 — Number。它的实现遵循 IEEE 754 标准,使用64位固定长度来表示,也就是标准的 double 双精度浮点数(相关的还有float 32位单精度)。
这样的存储结构优点是可以归一化处理整数和小数,节省存储空间。64位比特又可分为三个部分:

  • 符号位S:第 1 位是正负数符号位(sign),0代表正数,1代表负数
  • 指数位E:中间的 11 位存储指数(exponent),用来表示次方数
  • 尾数位M:最后的 52 位是尾数(mantissa),超出的部分自动进一舍零


    图片.png

在了解了存储的原理之后可能还不太理解。通过案例应该可以更加具体一点。
在执行计算0.1+0.2的过程中发生了什么?
因为计算机内部只能通过二级制处理数据,0.1和0.2会先被转换成二进制,但是由于浮点数用二进制表示时是无穷的,因此会被转换为:

0.1 -> 0.0001 1001 1001 1001...(1001循环)
0.2 -> 0.0011 0011 0011 0011...(0011循环)

相加之后就是0.0100 1100 ...(1100循环)
前面提到了,JavaScript提供的有效数字最长为53个二进制位(64位浮点的后52位+有效数字第一位的1)。最后的 52 位尾数超出部分发生了截断,因此,0.1+0.2的计算结果在截断后,二进制转换回十进制,得到的结果是0.30000000000000004


整数精度问题

前面提到了,既然小数存在,那整数也存在着上限。
js的Number自带存储了最大/最小安全整数
Number.MAX_SAFE_INTEGER === 9007199254740991(2^53 - 1)
Number.MIN_SAFE_INTEGER === -9007199254740991-(2^53 - 1)

至于为什么不是52次方-1。对于二进制来说, 小数点前保留一位, 规格化后始终是 1.***, 节省了 1 bit,这个 1 并不需要保存,所以可以多展示1位数,即2^53-1。

那么超出之后进行运算会发生什么就不用再解释了,原理同浮点数是一样的。


解决方案

除了自己造轮子的运算中进位,更推荐使用Math.js、decimal.js、big.js等类库,其中有完善的解决方案,具体想了解实现原理可以移步官方git直接查看函数方法。

不过通常不需要引入整个库,只需要其中的几个方法就适用了,例如常用的保留小数后几位(基于parseFloat和tofixed去改造……)


心得体会

前端的浮点数问题并不会太复杂,因为涉及到业务数据的计算通常都是交给后端完成,但是精确位数尤其是金额的展示还是不能出错。虽然涉及到计算机组成原理的知识,其实还是很容易弄懂的。


参考

JS中浮点数精度问题

相关文章

  • js精度问题

    关于js浮点数计算精度不准确问题的解决办法 今天在计算商品价格的时候再次遇到js浮点数计算出现误差的问题,以前就一...

  • js 处理四则运算失去精度问题

    js 处理四则运算失去精度问题 计算精度,特别是浮点数计算。举个栗子 然后我寻求各种解决办法,其中用了lodash...

  • js浮点数精度计算问题

    前言 项目中,总是不可避免会出现js的浮点数精度计算问题。抛出经典问题:为什么0.1===0.1,0.1+0.2!...

  • C 浮点数

    浮点数存储带来的问题 问题背景 计算机中浮点数(float或double类型)都有精度范围,对于超出精度范围的浮点...

  • js浮点金额计算精度

    在js中进行以元为单位进行浮点数计算时,会产生精度问题,例如: 大多数编程语言计算采用的是IEEE 754 标准,...

  • js浮点金额计算精度

    在js中进行以元为单位进行浮点数计算时,会产生精度问题,例如: 大多数编程语言计算采用的是IEEE 754 标准,...

  • 浮点数计算中的精度丢失

    1 js浮点数运算精度丢失 如果你用过js计算浮点数你肯定会遇到过下面这种情况:(我的小学白读了吗==。) (其...

  • Js中做减法时,出现小数位增加Bug

    这个bug是Js固有的,这是因为在javascript中浮点数的计算是以2进制计算的,浮点数精度不准。可以用下面方...

  • [js]数值的精度

    基础知识 js内部所有数字在计算机内存中的表示都是64位双精度浮点数 双精度浮点数表示法的副作用 使用二进制浮点数...

  • iOS中需要谨慎对待8.2这个数字

    咱们在开发中为了防止浮点数有精度问题,特意有NSDecimalNumber进行计算,来解决精度问题。 但是在开发中...

网友评论

    本文标题:js浮点数精度计算问题

    本文链接:https://www.haomeiwen.com/subject/mohamctx.html