≪ Today I learned.
RSS購読
    公開日
    タグ
    JavaScript
    著者
    ダーシノ

    BigIntで発生する誤差と対策

    ロシアの裁判所がとんでもない額(200溝ドル = 2*10^34)という賠償請求を命じた。

    JavaScriptで安全に扱える数はNumber.MAX_SAFE_INTEGERの値である9007199254740991(2^53-1)までだ。なので、200溝ドルという桁を扱うためにはBigIntを使う必要がある。

    BigIntを使うにはBigIntコンストラクタを使うか、数値リテラルの末尾にnをつけて表現する。

    BigIntの表現

    > 20000000000000000000000000000000000
    2e+34
    
    > BigInt(20000000000000000000000000000000000)
    19999999999999998911504619740856320n
    
    > 20000000000000000000000000000000000n
    20000000000000000000000000000000000n

    ?!?!

    BigInt(Number)で変換すると誤差が生じる。

    BigIntコンストラクタで生じる誤差

    BigInt(20000000000000000000000000000000000)のようにすると、コンストラクタにわたる前に数値が丸められてしまう。そのため、BigIntはすでにNumber型として丸められた19999999999999998911504619740856320を受け取るので結果に誤差が生じる。

    // 1. BigIntコンストラクタを使う
    BigInt(20000000000000000000000000000000000)
    
    // 2. 数値リテラルの部分が丸められてからBigIntに変換される
    BigInt(19999999999999998911504619740856320)
    
    // 3. 丸められた数値をBigIntが返ってくる
    19999999999999998911504619740856320n

    BigIntコンストラクタで誤差を避ける方法

    BigInt('20000000000000000000000000000000000')のように文字列リテラルでコンストラクタにわたすことで、数値が丸められることなくBigIntに変換される。

    > BigInt('20000000000000000000000000000000000')
    20000000000000000000000000000000000n