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