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/year/pending/proposal-bigint-from-exponential.md.
  • 简体中文
  • Bigint from exponential S2

    中文标题:从指数表示法构造 BigInt

    提案概览
    提案速览

    指数表示法在处理大整数时很有用,但无法直接用于定义 BigInt,且 BigInt(…) 在 2^53 以上会有损。该提案为静态用例提供 1e6n 这样的语法支持,并扩展 StringToBigInt,使 BigInt("1e6")、BigUint64Array.from(\["1e6"\]) 等动态用例能够解析指数表示法字符串。除非为保持向后兼容性作出明确更改,否则这一扩展也会影响运算符行为。还考虑了 BigInt.parse("1e6") 或 BigInt.fromString("1e6") 等替代方案。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    从指数表示法构造 BigInt

    状态

    TC39 流程

    阶段:2

    负责人:

    规范:http://tc39.es/proposal-bigint-from-exponential/

    动机

    指数表示法在处理大整数时很有用,但在定义 bigint 时无法直接使用。 使用 _ 分隔符有所帮助,但对于足够大的值来说仍不够。 BigInt(…) 在大于 253 时有损。 手动转换是可能的(例如,/^(?:(0|[1-9][0-9]*)(?:[.]([0-9]*))?|[.]([0-9]+))(?:[Ee]([+-]?[0-9]+))?$/ 会验证并匹配相关的整数/小数/十进制指数部分),但繁琐且乏味。

    用例

    这一点是在 Amount 中发现的,但也会出现在其他场景中(GitHub 报告有 20.3e3 个文件匹配模式 BigInt[(][^)a-z]*[0-9]e[0-9]):

    • 在可访问源文本的情况下解析像 { "scale": 1e6 } 这样的 JSON
    • 处理货币和/或金融值,尤其是细粒度的加密货币(例如,在 algorand-js 中)
    • 处理高分辨率日期或时间(例如,在 ECMAScript Temporal polyfill 和 WASI libraries 中)

    许多用例是静态的,其中指数表示法是源文本的一部分,而另一些用例是动态的,因此需要内置函数。

    描述

    对于静态用例,我们提议像 1e6n1 这样的语法支持。

    对于动态用例,我们提议按照 https://github.com/tc39/ecma262/pull/3857 的建议扩展 StringToBigInt 的行为,支持 BigInt("1e6")/BigUint64Array.from(["1e6"])/等。 注意,在没有为保持向后兼容性而作出明确更改时,这也会影响运算符行为(例如,1_000_000n == "1e6" 和 1_000_000n <= "1e6" 和 1_000_000n >= "1e6",就像 Number 的对应形式 1_000_000 == "1e6" 和 1_000_000 <= "1e6" 和 1_000_000 >= "1e6" 一样)。

    也可以考虑 BigInt.parse("1e6") 或 BigInt.fromString("1e6") 这样的替代方案。

    动态用例在技术上覆盖了静态用例,尽管会损害开发者体验和实现者满意度。

    现有技术

    一些 npm 包已经支持将指数表示法字符串解析为任意精度整数(或类似字符串):

    还有更多任意精度十进制库将这种行为推广到整数之外。

    在其他编程语言中,.NET BigInteger.Parse(str, options) 支持 AllowDecimalPoint 和 AllowExponent 选项,但似乎仅止于此:

    语言/API前导 +/-首尾空白基数前缀
    (例如 0x)
    分隔符
    (例如 _)
    小数/指数
    Go (new(big.Int)).SetString(str, 0)是否是是否
    Java new BigInteger(str, radix)是否不适用否否
    JavaScript BigInt(str)是是是否否
    .NET BigInteger.Parse(str, options)可选可选否可选可选
    Python int(str, base=0)是是是是否
    Rust num_bigint from_str_radix(&str, radix)是否不适用是否

    作为背景,ECMAScript 在严格性方面很不寻常:

    语言/API浮点数 → 任意精度整数
    Go (*big.Float).Int(new(big.Int))向零截断
    Java bigDecimal.toBigInteger()向零截断
    JavaScript BigInt(flt)拒绝非整数
    .NET new BigInteger(flt)向零截断
    Python int(flt)向零截断
    Rust num_bigint from_f64(flt)向零截断

    陈述历史

    实现

    Polyfill/转译器实现

    暂无。

    原生实现

    在 Stage 2.7 后查看此处。

    常见问题

    问:动态解析是否也应支持 _ 分隔符?

    答:不通过 BigInt(string),但也许可通过其他 API。

    问:动态解析是否应可配置?

    答:除非对数字也这样做,否则不应可配置,而那似乎是一个单独的提案。

    问:是否允许小数,例如 BigInt("86.4e12") === 86_400_000_000_000n?

    答:允许,这对于保持精度的规范形式很重要(例如,区分 1.000e3n 和 1e3n)。

    问:#8 是否允许负指数,例如 1230e-1n === 123n?

    答:待定。将支持限制为非负指数并不困难。

    问:#9 改变 1_000_000n == "1e6" 和 1_000_000n <= "1e6" 和 1_000_000n >= "1e6" 的行为是否与 Web 兼容?

    答:待定,但如果不是,那么在仍支持主要用例的同时,仍有可能划出例外。

    Footnotes

    1. 这在广泛使用的编程语言中可能是前所未有的(参见 https://github.com/tc39/ecma262/pull/3857#issuecomment-4960986324)。 ↩