小数计算的精度问题
先理解js存储number数据的格式
JS 采用 IEEE 754 双精度64位标准储存number类型数据
JS的浮点数实现遵循IEEE 754标准,采用双精度存储(double precision),使用64位固定长度来表示,其中1位用来表示符号位,11位用来表示指数,52位表示尾数。如下图:
- 符号位(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 不存在上诉问题,
但不代表其他 浮点数也是特殊情况,待探究!!!