Math.sumPrecise S4
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2026
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了 Math.sumPrecise,这是一个接受可迭代对象并返回其数值总和的方法,精度高于朴素求和。它解决了求和列表的常见操作,并提高了浮点数的准确性。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
Math.sumPrecise
一个向 JavaScript 添加求和多个值的方法的提案。
状态
作者:Kevin Gibbons
提案负责人:Kevin Gibbons
该提案处于 TC39 流程 的第 3 阶段:该提案已准备好进行实现。测试 在 test262 中可用。有关实现状态,请参阅 issue #19。
动机
求和是一个非常常见的操作,并且是 Array.prototype.reduce 的少数剩余用例之一。最好让用户直接表达该操作。
此外,对浮点数列表求和可以比朴素的 .reduce((a, b) => a + b, 0) 方法更精确,通过使用更巧妙的算法,这一事实很少 JavaScript 程序员知道(而且即使知道,大多数人也懒得去做)。我们可以让更好的选项更容易被使用。
提案
添加一个接受可迭代对象的 Math.sumPrecise 方法,该方法使用比朴素求和更精确的算法返回可迭代对象中值的总和。
问题
使用哪种算法?
而不是指定任何特定算法,此提案要求最大正确的结果——即如果进行任意精度算术,然后将结果转换回浮点数得到的结果。这可以在不需要实际任意精度算术的情况下完成。一种实现方式在 Shewchuk '96 中给出,我已经在 JS 中 实现了(加上一些处理中间溢出的细节)。其他策略也有可能。
Python 的 math.fsum 目前使用相同的算法实现(虽然不处理中间溢出)。
一个更新的算法在 Radford M. Neal 的 使用小和大超级累加器进行快速精确求和 中给出,其 MIT 许可的代码可 在此处 获取。
接受可迭代对象还是可变参数?
Math.max 的先例表明可变参数,但这并不是你真正想要的——一旦你的列表超过几万个元素,你可能会溢出栈并获得 RangeError。
因此,此提案仅包含接受可迭代对象的形式。
命名
Math.sum 是显而易见的名称,但很明显这将是一个与朴素求和不同的(更慢的)算法。这被称为 Math.sumPrecise 以提醒这一差异。
是否应将事物强制转换为数字,或者如果给定了不是数字的东西是否抛出异常?
它将拒绝非数字值,打破 Math.max 的先例。
空列表的总和是 0 还是 -0?
是 -0。这是浮点加法恒等元素。这个选择确保 Math.sumPrecise([]) + Math.sumPrecise(foo) 总是给出与 Math.sumPrecise(foo) 相同的答案。
是否应该支持 BigInt?
不 - 重要的是 Math.sumPrecise([]) 返回数字 -0(或 0),这意味着当 bigints 为空时,5n + Math.sumPrecise(bigints) 将抛出异常,这将是不好的。
我们可能有单独的方法来对 BigInt 求和。根据上述命名讨论的结果,我会投票给 BigInt.sum 或 BigInt.sumFrom。但这样的方法不会成为此提案的一部分。
那么乘积呢?
这种情况出现得较少,所以我目前不提出它。