配了三年财务图表,今天才知道那几分钱的误差从来不是算法问题——Math.sumPrecise() 今天把这件事彻底修了

前端工程师大概都遇到过这个场景:订单总价 0.1 + 0.2 + 0.15 算出来是 0.45000000000000007,要么在展示层 round 一下,要么整个商品金额都乘 100 走整数运算。这个「修」法从 jQuery 时代流传到现在,2026 年了还在用。

ES2026 给了标准答案:Math.sumPrecise()。

它解决的是什么

JavaScript 的 Number 类型是 IEEE 754 双精度浮点,0.1 + 0.2 在二进制里是无限循环小数,存储时就被截断了,运算结果自然带误差。单个运算误差极小,但在循环累加里会不断积累——1 万条 0.1 元商品累计就能跑出 1 分钱以上的偏差。财务系统、传感器聚合、图表数据处理,这三类场景最容易踩到这个坑。

传统解法有三个方向:乘 100 转整数 → 结算时要记得除回去,还要处理除法引入的新精度问题;toFixed + Number 转字符串 → 只能处理展示,不能做中间态运算;第三方大数库(如 decimal.js)→ 依赖多、bundle 体积大、API 风格和原生完全不同。三个方向都是修修补补,没有一个从语言层面解决。

Math.sumPrecise() 怎么做到的

它的核心是 Shewchuk’s algorithm。运算过程中同时维护两个值:当前估算和累计误差。每次相加时,把误差单独记录并在下一步补偿回来,最终返回修正后的结果。对外只暴露精确的求和结果,内部误差处理全部自动化。

效果对比:

// 传统 reduce
[0.1, 0.2, 0.3].reduce((a, b) => a + b, 0)
// 0.6000000000000001

// Math.sumPrecise
Math.sumPrecise([0.1, 0.2, 0.3])
// 0.6

// 累计误差场景
const items = Array(10000).fill(0.1)
items.reduce((a, b) => a + b, 0)
// 1000.0000000001588,有明显 drift

Math.sumPrecise(items)
// 1000,精确

还有一个容易被忽视的坑:1e20 + 1 – 1e20 用传统方式会直接等于 0(因为 1 在 1e20 面前丢失了精度),但 Math.sumPrecise 会正确返回 1。这个 case 在财务报表里概率极低,但一旦出现就是严重的数据错误。

浏览器支持情况

2026 年 4 月进入 Baseline Widely Available。Chrome 137+、Firefox 137+、Safari 26.2+、Edge 147+、Node 22+ 全部支持。Global 覆盖率已超过 93%,生产环境可以直接用,不用 polyfill。

如果需要兼容极老的浏览器,可以用这个写法兜底:

function sum(arr) {
if (typeof Math.sumPrecise === ‘function’) {
return Math.sumPrecise(arr)
}
// 降级方案:kahan summation(精度不如 sumPrecise 但比 naive reduce 好)
let sum = 0, err = 0
for (const v of arr) {
const y = v – err
const t = sum + y
err = (t – sum) – y
sum = t
}
return sum
}

落地三步

第一步:全局搜索项目里有没有自己写的 sum/reduce 求和函数,特别是涉及金额、数量累加的。如果有,优先在对应场景替换成 Math.sumPrecise。第二步:新项目或重构时,涉及财务计算、传感器读数、图表数据聚合的代码,直接用 Math.sumPrecise 替代 reduce((a,b)=>a+b,0)。第三步:@ts-ignore 可以不加——TypeScript 内置类型已经更新,sumPrecise 的签名是 sumPrecise(values: Iterable<number>): number,类型安全。

总结一下:修修补补十几年的浮点精度问题,现在一行代码解决了。但要注意它的作用域——它只解决「多个浮点数求和过程中的精度损失」,不解决 0.1 本身无法精确表示的问题(那是二进制存储层的限制,没法绕开),也不处理溢出、科学计数法边界情况。这几个场景还是要靠大数库或者专门的 Decimal 类型。理解了这个边界,Math.sumPrecise 就是近十年来 JS 数值计算领域最实用的新 API。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 10 阅读