BigInt
BigInt
はプリミティブラッパーオブジェクトで、プリミティブの bigint
値、すなわち大きすぎて number
プリミティブで表すことができない数を、表現したり操作したりするために使用します。
解説
BigInt 値は、単に BigInt と呼ばれることもありますが、 bigint
プリミティブです。整数リテラルの末尾に n
を追加するか、 BigInt()
コンストラクターを呼び出し、整数値または文字列値を与えることで生成することができます (ただし new
演算子なしで)。
const previouslyMaxSafeInteger = 9007199254740991n
const alsoHuge = BigInt(9007199254740991)
// ↪ 9007199254740991n
const hugeString = BigInt("9007199254740991")
// ↪ 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff")
// ↪ 9007199254740991n
const hugeOctal = BigInt("0o377777777777777777")
// ↪ 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111")
// ↪ 9007199254740991n
BigInt はいくつかの点で Number と似ていますが、重要ないくつかの点が異なります。組み込みの Math
オブジェクト内のメソッドでは利用できず、演算で Number の値と混ぜることができません。同じ型に統一する必要があります。ただし、BigInt を Number へ変換する際には精度が落ちることがあるので、相互に変化する場合には注意が必要です。
型情報
typeof
の BigInt
値 (bigint
プリミティブ) に対する評価値は、"bigint
" となります。
typeof 1n === 'bigint' // true
typeof BigInt('1') === 'bigint' // true
BigInt の値は Object
でラップすることができます。
typeof Object(1n) === 'object' // true
演算子
以下の演算子は BigInt 値またはオブジェクトでラップした BigInt 値で使用することができます。
+ * - % **
ビット操作演算子は、同様に利用できますが、 >>>
(論理的右シフト) は BigInt が常に符号付きなので除外されます。
同様に、単項演算子 (+
) は asm.js を壊さないように対応していません。
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER)
// ↪ 9007199254740991n
const maxPlusOne = previousMaxSafe + 1n
// ↪ 9007199254740992n
const theFuture = previousMaxSafe + 2n
// ↪ 9007199254740993n, this works now!
const multi = previousMaxSafe * 2n
// ↪ 18014398509481982n
const subtr = multi - 10n
// ↪ 18014398509481972n
const mod = multi % 10n
// ↪ 2n
const bigN = 2n ** 54n
// ↪ 18014398509481984n
bigN * -1n
// ↪ -18014398509481984n
/
演算子もすべての数値に対して、期待される通りに動作します。ただし、実数との演算では BigInt 値と演算する際に小数が切り捨てられます。実数を返すことはありません。
const expected = 4n / 2n
// ↪ 2n
const truncated = 5n / 2n
// ↪ 2n, not 2.5n
比較演算
BigInt 値は Number 値と厳密等価ではありませんが、等価にはなります。
0n === 0
// ↪ false
0n == 0
// ↪ true
Number と BigInt は通常通り比較できます。
1n < 2
// ↪ true
2n > 1
// ↪ true
2 > 2
// ↪ false
2n > 2
// ↪ false
2n >= 2
// ↪ true
BigInt 値と Number 値は配列の要素に混在させたり並べ替えたりすることも可能です。
const mixed = [4n, 6, -12n, 10, 4, 0, 0n]
// ↪ [4n, 6, -12n, 10, 4, 0, 0n]
mixed.sort() // 既定の並べ替えの動作
// ↪ [ -12n, 0, 0n, 10, 4n, 4, 6 ]
mixed.sort((a, b) => a - b)
// 型が混在した減算はできないので動作しない
// TypeError: can't convert BigInt value to Number value
// 適切な数値比較関数を使用した並べ替え
mixed.sort((a, b) => (a < b) ? -1 : ((a > b) ? 1 : 0))
// ↪ [ -12n, 0, 0n, 4n, 4, 6, 10 ]
なお、 Object
にラップされた BigInt は他のオブジェクトと同様の振る舞いをします。同じインスタンス同士が比較された場合にのみ等価となります。
0n === Object(0n) // false
Object(0n) === Object(0n) // false
const o = Object(0n)
o === o // true
条件式
BigInt 値は次のような場合は Number 値のように動作します。
if (0n) {
console.log('Hello from the if!')
} else {
console.log('Hello from the else!')
}
// ↪ "Hello from the else!"
0n || 12n
// ↪ 12n
0n && 12n
// ↪ 0n
Boolean(0n)
// ↪ false
Boolean(12n)
// ↪ true
!12n
// ↪ false
!0n
// ↪ true
コンストラクター
BigInt()
-
新しい BigInt 値を生成します。
静的メソッド
BigInt.asIntN()
-
BigInt 値を符号付き整数値に丸め、その値を返します。
BigInt.asUintN()
-
BigInt 値を符号なし整数値に丸め、その値を返します。
インスタンスメソッド
BigInt.prototype.toLocaleString()
-
この BigInt 値の言語に合わせた表現の文字列を返します。
Object.prototype.toLocaleString()
メソッドを上書きします。 BigInt.prototype.toString()
-
この BigInt 値を指定された基数で表現した文字列を返します。
Object.prototype.toString()
メソッドを上書きします。 BigInt.prototype.valueOf()
-
この BigInt 値を返します。
Object.prototype.valueOf()
メソッドを上書きします。
使用方法の推奨事項
型変換
Number 値と BigInt 値との間の型変換は精度が落ちる可能性があるため、次のことを推奨します。
- BigInt 値は、値が 2^53 を超えることが合理的に予想される場合にのみ使用する。
- BigInt 値と Number 値の間で型変換を行わない。
暗号処理
BigInt で対応している演算は、実行時間が一定ではないので、タイミング攻撃を受ける可能性があります。したがって、 JavaScript の BigInt は暗号処理での使用には向きません。
JSON での使用
JSON.stringify()
を BigInt 値に対して使用すると TypeError
が発生します。 BigInt 値は既定で JSON のシリアライズに対応していないためです。ただし、 replacer 引数を JSON.stringify
で使用すると、 BigInt のプロパティをエラーなしでシリアライズすることができます。
function replacer(key, value) {
if (key === 'big') {
return value.toString();
}
return value;
}
const data = {
number: 1,
big: BigInt('18014398509481982'),
};
const stringified = JSON.stringify(data, replacer);
console.log(stringified);
// ↪ '{"number":1,"big":"18014398509481982"}'
長整数になる値が含まれると思われる JSON データがある場合は、 reviver 引数を JSON.parse
で使用することで取り扱うことができます。
function reviver(key, value) {
if (key === 'big') {
return BigInt(value);
}
return value;
}
const payload = '{"number":1,"big":"18014398509481982"}';
const parsed = JSON.parse(payload, reviver);
console.log(parsed);
// ↪ {number: 1, big: 18014398509481982n}
例
素数の計算
// 渡された BigInt が素数であった場合は true を返します
function isPrime(p) {
for (let i = 2n; i * i <= p; i++) {
if (p % i === 0n) return false;
}
return true
}
// 引数として BigInt 値を取り、 nth 番目の素数を BigInt 値として返します。
function nthPrime(nth) {
let maybePrime = 2n
let prime = 0n
while (nth >= 0n) {
if (isPrime(maybePrime)) {
nth--
prime = maybePrime
}
maybePrime++
}
return prime
}
nthPrime(20n)
// ↪ 73n
仕様書
Specification |
---|
ECMAScript Language Specification # sec-bigint-objects |
ブラウザーの互換性
BCD tables only load in the browser