小数计算的精度问题

先理解js存储number数据的格式

JS 采用 IEEE 754 双精度64位标准储存number类型数据

JS的浮点数实现遵循IEEE 754标准,采用双精度存储(double precision),使用64位固定长度来表示,其中1位用来表示符号位,11位用来表示指数,52位表示尾数。如下图:

java中的双精度型的加减 js 双精度_前端


- 符号位(sign):第1位是正负数符号位,0代表正数,1代表负数

- 指数位(Exponent):中间11位存储指数,用来表示次方数

- 尾数位(mantissa):最后的52位是尾数,超出部分自动进一舍零

再谈原因

  • 计算过程:十进制浮点数 转换位 二进制进行运算,得到的结果再转换位十进制
  • !!浮点数值!!真实的二进制!!表示出来是无穷的
0.1 二进制表示——>0.0001 1001 1001 1001 ...(1001循环)
0.2 二进制表示——>0.0011 0011 0011 0011 ...(0011循环)
//其他浮点数类似
  • !!JS中采用的 IEEE754标准的64位双精度浮点数的小数部分!!!最多支持53位二进制!!!所以浮点数真实的二进制表示的数字被截断
  • 参与计算的浮点数的 二进制其实不完整 ,所得到的的值的二进制也不完整,此时将二进制结果转换位十进制得到的数值就有误差,不正确


解决方案

方案一(最简单) : 乘于10 成为 >1的数 后期在除10

0.1 + 0.2 // 0.30000000000000004 -- 5个000

((0.1*10)+(0.2*10))/10  //0.3

方案二: 引用JS三方库工具

  • Math.js (使用参考 – JS计算小数精度丢失解决方案 - Math.js)
  • decimal.js
  • big.js

方案三:自定义处理函数

借用 推荐文章中有介绍

JS浮点数四则运算

拓展

0.01 + 0.02 不存在上诉问题,

但不代表其他 浮点数也是特殊情况,待探究!!!

java中的双精度型的加减 js 双精度_浮点数_02