For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/proposal-math-sum.md.
  • 简体中文
  • Math.sumPrecise S4

    提案概览
    提案速览

    该提案引入了 Math.sumPrecise,这是一个接受可迭代对象并返回其数值总和的方法,精度高于朴素求和。它解决了求和列表的常见操作,并提高了浮点数的准确性。

    Note

    以下 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 方法,该方法使用比朴素求和更精确的算法返回可迭代对象中值的总和。

    let values = [1e20, 0.1, -1e20];
    
    values.reduce((a, b) => a + b, 0); // 0
    
    Math.sumPrecise(values); // 0.1

    问题

    使用哪种算法?

    而不是指定任何特定算法,此提案要求最大正确的结果——即如果进行任意精度算术,然后将结果转换回浮点数得到的结果。这可以在不需要实际任意精度算术的情况下完成。一种实现方式在 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.sumBigInt.sumFrom。但这样的方法不会成为此提案的一部分。

    那么乘积呢?

    这种情况出现得较少,所以我目前不提出它。