场景
数字相减
111.00-222.20 // -111.19999999999999
数字相加
1.10+2.20 // 3.3000000000000003
数字相乘
0.3*3 // 0.8999999999999999
数字相除
0.3/3 // 0.09999999999999999
原因分析
JavaScript中的数字运算遵循IEEE 754标准的浮点数算法,这种算法使用二进制来表示实数,以及对实数进行加、减、乘、除等运算。然而,由于二进制不能准确地表示所有的十进制小数,因此,进行数字运算时可能会出现无限小数。
例如,0.1在二进制中是一个无限循环的小数,用64位浮点数表示时就会出现精度误差。如果对0.1和0.2进行加法运算,期望结果是0.3,但是实际结果可能是0.30000000000000004,这是由于二进制表示的精度问题造成的。
解决方案
先乘以10000转成整数计算后再除以10000,(这里的10000可以自己根据需要调整)
例如:1.1+2.2Math.round(1.1 * 10000 + 2.2 * 10000)/10000 // 3.3
使用字符串或数组等数据结构来模拟数学运算中的处理过程
具体来说,当计算两个数字相加时,高精度计算库会将数字的每一位分别相加,并且在需要的时候进行进位操作;当计算乘法时,当前位的计算结果是将当前数字的每一位乘以另一个数对应位的数字后相加得到的。
该方法比较复杂,别人已经写有类似的库,我们可以借鉴
以下是一些常用的第三方库:
BigNumber.js:这是一个功能强大的库,支持高精度整数、小数和有理数运算。它提供了类似于JavaScript内置数字类型的API,例如加、减、乘、除等运算,以及比较、取余、幂等运算等。
decimal.js:这是一个基于JavaScript的高精度计算库,支持任意精度的小数运算。它提供了诸如加、减、乘、除等基本运算,还支持一些高级运算,例如求正弦、余弦、幂运算等。
bignumber.js:这也是一个流行的高精度计算库,支持任意精度的整数和小数计算。它提供了相对较小、内存占用低的API,适用于较小的高精度计算场景。