JavaScript中parseFloat处理负数保留两位小数时出现异常计算结果
问题原因
你遇到的结果和parseFloat没有关系,是JavaScript采用IEEE 754 双精度浮点数存储数字的固有特性导致的精度误差。
原始计算的误差来源
你第一段代码的理想计算结果应该是:
-8985.69 + 8985.915 - 0.23 = -0.005
但0.69、0.915、0.23这类十进制小数无法被二进制浮点数精确表示,存储时本身就存在微小偏差,多次运算后偏差累积,就得到了和-0.005非常接近的-0.004999999999636212。
极小值结果的来源
你调用toFixed(2)后,三个值的理想转换结果为:
x.toFixed(2)→ "-8985.69"y.toFixed(2)→ "-8985.92"(-8985.915四舍五入保留两位小数的结果)z.toFixed(2)→ "0.23"
理想运算结果应该是:
-8985.69 - (-8985.92) - 0.23 = 0
但哪怕是两位小数的十进制数,也可能无法被IEEE 754浮点数精确表示,parseFloat把字符串转回数字时,会按照浮点数规则存储,本身就携带了微小的精度偏差。三个带偏差的数值做减法后,大部分偏差抵消,残留的极小偏差就是你看到的-4.365674488582272e-13,这个值和0的差异完全可以忽略,属于浮点数运算的正常现象。
你可以直接运行以下代码验证,和parseFloat无关,直接用数字字面量运算也会得到同样的结果:
console.log(-8985.69 - (-8985.92) - 0.23) // 输出:-4.365674488582272e-13
常见解决方案
如果需要精确计算,可以选择以下方案:
- 运算后保留指定小数位输出,比如
temp2.toFixed(2)就能得到"0.00"的结果 - 把小数放大为整数运算,全部计算完成后再缩放到对应小数位
- 精度要求极高的场景可以使用专门的大数运算库
内容的提问来源于stack exchange,提问作者Cineno28
相关产品推荐
相关产品推荐

