配了多年精度计算,今天才知道浮点把结果偷偷吃掉了——Math.sumPrecise() 把这件事从根上原生化了
做过财务结算、统计数据,甚至只是给图表算个累计值的工程师,大概都见过这个经典场面:0.1 + 0.2 的结果不是 0.3,而是 0.30000000000000004——这个笑话说了好多年,2026 年 JavaScript 终于给出了一个官方的解法。
它不是修 0.1 + 0.2 的问题
先别急着高兴。Math.sumPrecise() 不能让 0.1 + 0.2 变成精确的 0.3,这件事 IEEE 754 浮点数的底层限制改不了。这个 API 解决的是另一个更隐蔽、但在实际业务里更致命的问题:累积误差。
看这个例子:
// 经典 reduce 求和
const values = [1e20, 0.1, -1e20];
const total = values.reduce((a, b) => a + b, 0);
console.log(total); // 0
// Math.sumPrecise 求和
console.log(Math.sumPrecise(values)); // 0.1
1e20 + 0.1 这一步,在 IEEE 754 双精度浮点数里,0.1 相对于 1e20 太小了,直接被四舍五入成了 0。然后 1e20 + (-1e20) = 0,最终结果 0。数学上等于 0.1,但 reduce 算出来是 0。
这种事在真实场景里比想象中常见:报表合计差个几分钱、日志聚合数字对不上、传感器数据积分越算越偏——往往不是算法错了,是浮点精度在中间步骤悄悄吃了你的数据。
API 怎么用
// 接收任意可迭代对象
const total = Math.sumPrecise([10, 20, 30]); // 60
// 财务场景
const orders = [899.99, 1299.00, 59.99, 199.00];
console.log(Math.sumPrecise(orders)); // 2457.98
// 科学计算
const measurements = [1e10, 0.0001, -1e10];
console.log(Math.sumPrecise(measurements)); // 0.0001
// 降级兼容
const sum = Math.sumPrecise
? Math.sumPrecise(values)
: values.reduce((a, b) => a + b, 0);
底层原理是”高精度求和算法”:不是一次次做 sum + nextNumber 再四舍五入,而是先把所有数字以高精度累加,最后再转换成最接近的可表示 64 位浮点数。MDN 的描述是”仿佛先用精确数学值求和,再取最近的可表示浮点结果”。
浏览器支持
| 浏览器 | 版本 |
|---|---|
| Chrome | 147+ |
| Firefox | 137+ |
| Safari | 26.2+ |
| Edge | 147+ |
它是 ES2026 的一部分,2026 年 4 月进入 Baseline “Newly Available”。目前全球覆盖率约 79%(caniuse 数据),不支持的浏览器可以自己写降级函数,等覆盖率再涨一到两年就稳了。
什么时候用它
应该用: 财务金额累加、统计数据合计、传感器读数积分、任何”差个零点零几会出大事”的场景。
不需要用: UI 动画参数、简单的 UI 数字展示、用户可见度不高的装饰性计数。
说白了,这是一个”有体感才值得用”的 API——如果你的用户会因为合计差了几分钱来投诉,这个 API 就是为你准备的;如果只是给 div 里的数字做一下加法,原来的 reduce 完全够用。
下一个要写累加逻辑之前,先看一眼 Math.sumPrecise() 有没有:如果有,三行代码换掉 reduce;如果没有,想想这个场景值不值得加一个降级兼容。这个 API 不会解决 0.1 + 0.2 的问题,但它解决的是更隐蔽、更影响业务的精度丢失。2026 年了,财务计算该用更精确的方式了。
评论区
登录后可评论。