You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript货币计算乘100转整数时浮点精度异常排查

异常原因

JavaScript 中所有数值都遵循 IEEE 754 双精度浮点数存储标准,这类存储逻辑使用二进制分数记录数值,大量十进制小数无法被二进制精确表示——和十进制体系下无法精确写出1/3的有限小数形式是一个道理。
你看到只有2.05乘100出问题,不代表其他数值的计算没有误差:1.01、3.1这类值本身存储时就不是精确的十进制值,只是它们乘100之后的误差极小,小到控制台输出时自动舍入成了整数,肉眼看不到偏差而已。2.05本身的存储值比真实值略小,乘100后误差被同步放大得到204.99999999999997,这个偏差刚好超过了控制台默认的舍入阈值,才把精度问题暴露了出来。

无第三方库的解决方法

考核项目不允许引入外部库的场景下,用原生方法即可彻底规避这个问题:

  • 所有浮点数乘100转分单位的逻辑,外层统一包裹Math.round()做四舍五入取整,不要直接使用乘法结果。不要用parseInt处理这类转换,parseInt是字符串解析方法,对数字的处理逻辑存在额外边界问题,Math.round刚好可以把浮点数误差带来的微小偏差修正为正确整数。
  • 转换完成后,所有金额相关的运算全程使用分单位的整数计算,不要在逻辑判断、数值比较环节切回元单位的浮点数,直到最终需要给用户展示结果时,再做除法转换为元单位格式,避免中间运算反复引入精度问题。

修正后的代码如下:

function checkCashRegister(price, cash, cid) {
  price = Math.round(price * 100);
  cash = Math.round(cash * 100);

  for (let i = 0; i < cid.length; i++) {
    cid[i][1] = Math.round(cid[i][1] * 100);
  }

  console.log(price);
  console.log(cash);
  console.log(cid);
}

console.log(
  checkCashRegister(19.23, 200, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])
);

运行上述代码后,NICKEL对应的值会正确输出为205,所有金额转换结果均符合预期。

内容的提问来源于stack exchange,提问作者Chris Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:09:30