JS 浮点数相加出现精度不准确问题

1,782 阅读2分钟

title: JS 浮点数相加出现精度不准确问题

JS 浮点数相加出现精度不准确问题

场景还原:最近在做公司的一个点餐项目时,遇到添加商品计算总价的需求,自然而然的用最原始的方法实现。但当我计算到6 + 0.01 + 0.01 + 0.02 时,居然不等于6.04。一开始及其懵逼反复检查了自己的逻辑代码,发现都没问题。最后只能找度娘,发现原来这是js 本身的问题, 由于存在二进制和十进制的转换问题,具体的位数会发生变化 。我默默打开浏览器控制台,验证一下,果不其然,下面的浏览器控制台的打印结果:

Image text

对于这个问题,有两个解决办法:1,toFixed() 2,自定义方法转换

方案一:toFixed()

将每次相加的和用toFixed()这个方法转一下,就可以得到保留两位小数的浮点数。这个方法比较简单,适合用于精度要求不高的场景

方案二:自定义函数

先贴代码:

getSum:function (num1, num2) {
    let sq1 = 0
    let sq2 = 0
    let m = 0
    try {
    	sq1 = num1.toString().split('.')[1].length
    } catch (error) {
    	sq1 = 0
    }
    try {
    	sq2 = num2.toString().split('.')[1].length
    } catch (error) {
    	sq2 = 0
    }
    m = Math.pow(10, Math.max(sq1, sq2))
    return (num1 * m + num2 * m) / m
}

注意:Math.powMath.max,可以先了解一下js的这个内置方法,在这里就不多阐述了

思路:这个方法的逻辑就是传入两个要求和的数字(前提必须是数字),首先假设传入的是小数,通过toString().split('.')[1].length,将小数转为字符串然后以(‘ . ’)切割字符串并且取到后半部分的长度,所以sq1,sq2分别取到的是两个小数的小数位数。Math.max(sq1, sq2)得到最大的小数位数,Math.pow(10, Math.max(sq1, sq2))得到10的最大小数位数幂。

总结:把需要计算的数字乘以 10 的 n 次幂,换算成计算机能够精确识别的整数,然后再除以 10 的 n 次幂,这样就能得到精度准确的小数