JavaScriptには扱える整数値の範囲に制限があります。
範囲内での整数演算は正確に行われますが、範囲外での整数演算は正確に行われません。
これを防ぐために、JavaScriptではMAX_SAFE_INTEGER
とMIN_SAFE_INTEGER
というプロパティが用意されています。
この記事では、MAX_SAFE_INTEGER
とMIN_SAFE_INTEGER
について、以下の内容をサンプルコードを用いてわかりやすく解説します。
MAX_SAFE_INTEGER
とはMIN_SAFE_INTEGER
とは- なぜ
2^53 - 1
が上限なのか? Number.isSafeInteger()
で安全な範囲を確認するBigInt
で大きな数値を安全に扱う
MAX_SAFE_INTEGERとは
JavaScriptのNumberオブジェクトにはMAX_SAFE_INTEGER
というプロパティがあります。
MAX_SAFE_INTEGER
は、JavaScriptで安全に(誤差なく)扱える最大の整数値です。MAX_SAFE_INTEGER
の値は2^53 - 1
、つまり9007199254740991
に相当します。
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
MAX_SAFE_INTEGER
より大きい数値を使った場合、整数演算や比較が正確に行われません。たとえば、以下のようなコードを実行してみましょう。
console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992 (誤った結果)
console.log(9007199254740991 === 9007199254740992); // false
console.log(9007199254740991 + 1 === 9007199254740991 + 2); // true (誤った結果)
本来であれば9007199254740991 + 2
は9007199254740993
になるはずですが、範囲外に達したため正確な結果が得られなくなっています。
MIN_SAFE_INTEGERとは
JavaScriptにはMAX_SAFE_INTEGER
と同様に、MIN_SAFE_INTEGER
も存在します。
MIN_SAFE_INTEGER
は、JavaScriptで安全に(誤差なく)扱える最小の整数値です。MIN_SAFE_INTEGER
の値は-(2^53 - 1)
、つまり-9007199254740991
に相当します。
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
MIN_SAFE_INTEGER
をより小さい数値を使った場合、整数演算や比較が正確に行われません。たとえば、以下のようなコードを実行してみましょう。
console.log(-9007199254740991 - 1); // -9007199254740992
console.log(-9007199254740991 - 2); // -9007199254740992 (誤った結果)
console.log(-9007199254740991 === -9007199254740992); // false
console.log(-9007199254740991 - 1 === -9007199254740991 - 2); // true (誤った結果)
本来であれば-9007199254740991 - 2
は-9007199254740993
になるはずですが、範囲外に達したため正確な結果が得られなくなっています。
なぜ 2^53 - 1 が上限なのか?
MAX_SAFE_INTEGER
の値が2^53 - 1
、MIN_SAFE_INTEGER
の値が-(2^53 - 1)
になっている理由は、JavaScriptの数値が倍精度浮動小数点数(IEEE 754 標準)で表現されているからです。
倍精度浮動小数点数では、全体で64ビットを使い、その内訳は次の通りです。
- 1ビットが符号ビットに割り当てられており、正の数か負の数かを示します。
- 11ビットが指数部に使われます。
- 52ビットが仮数部に割り当てられており、さらに隠れた1ビットとして常に1が仮定されているため、実質的には53ビットの精度で整数を表現できます。
そのため、JavaScriptでは安全に扱える整数の範囲が-(2^53 - 1)
から2^53 - 1
までとなっています。
Number.isSafeInteger()で安全な範囲を確認する
JavaScriptでは、Number.isSafeInteger()
を使用して、数値が安全に(誤差なく)扱える範囲内であるかどうかを確認できます。
console.log(Number.isSafeInteger(9007199254740991)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false
console.log(Number.isSafeInteger(-9007199254740991)); // true
console.log(Number.isSafeInteger(-9007199254740992)); // false
この関数を使うことで、大きすぎる数値や小さすぎる数値によるエラーを防ぐことができます。
BigIntで大きな数値を安全に扱う
MAX_SAFE_INTEGER
より大きな整数やMIN_SAFE_INTEGER
より小さな整数を扱いたい場合は、JavaScriptのBigInt
型を使用します。BigInt
は、任意の大きさの整数を正確に表現できるデータ型です。
let largeNumber = BigInt(9007199254740991) + BigInt(2);
console.log(largeNumber); // 9007199254740993n
BigInt
を使うことで、整数の範囲制限を気にせずに安全に大きな数値を操作できます。ただし、BigInt
型と通常のNumber
型の数値を直接混ぜて計算することはできないため、注意が必要です。
let num = 10;
let bigIntNum = BigInt(20);
console.log(num + bigIntNum);
// エラー
// TypeError: Cannot mix BigInt and other types, use explicit conversions
このような場合、数値の型を揃える必要があります。
本記事のまとめ
この記事ではMAX_SAFE_INTEGER
とMIN_SAFE_INTEGER
について、以下の内容を説明しました。
MAX_SAFE_INTEGER
とはMIN_SAFE_INTEGER
とは- なぜ
2^53 - 1
が上限なのか? Number.isSafeInteger()
で安全な範囲を確認するBigInt
で大きな数値を安全に扱う
お読み頂きありがとうございました。