Chrome67およびNode v10(フラグ付き)において、BigIntがサポートされました。BigIntを使えば任意精度の整数値を扱うことができるようになります。
この記事では、BigIntの簡単な使い方を解説します。
Numberの限界とBigInt
JavaScriptのNumber(数値型)は倍精度浮動小数点数となります。つまり全体が64bitで、仮数部が52bitです。仮数部が52bitなので、Numberを用いて正確に表せる最大の整数は、53bitで表せる数から1引いた数になり、(2^53 – 1) = 9007199254740991となります。この「正確に表せる最大数」については定数にもなっていて、Number.MAX_SAFE_INTEGERで9007199254740991を得ることもできます。
Numberで表せる最大の整数値は十分な値にも思えますが、分野によってはこれでも足りなくなることがあります。そこで導入されたのがBigIntです。
BigIntは、任意精度の整数を表す新しいプリミティブ型です。任意精度の整数値については、基本的にCPUに搭載されている計算機は対応していないので、計算はソフトウェアによって行われます。
対応ブラウザ
BigIntの対応ブラウザは以下の通りです:
- Chrome: 67
- Firefox: 対応予定
- Safari: 対応予定
- Edge: 未定
また、Node v10において、–harmony-bigintオプションをつけることでBigIntを使用することが可能です。
BigIntの作り方
BigIntを利用するのは簡単で、リテラル記法が用意されています。またBigInt(value)関数を用いることでも作成できます。
// 数値の後に「n」をつけることでBigIntになる。
const bi1 = 123456n;
// BigInt関数を使うことでも作成が可能。
const bi2 = BigInt(123456);
末尾に「n」さえつければ2進数や8進数、16進数で記述することも可能です。
const bin = 0x101n
const oct = 0o640n;
const hex = 0x100n;
BigIntの基本的な使い方はたったこれだけです!
BigIntの演算
BigIntは、当然ながら演算も行えます。足し算(+)、引き算(-)、掛け算(*)、累乗(**)、割り算(/)、剰余(%)の計算ができます。また、各種ビット演算も行えます。
const biSum = 1n + 2n;
const biDiff = 1n - 2n;
ただしこのとき、以下の制約があります:
- 比較演算子を除き、演算子の両辺はともにBigIntでなければいけない(計算にNumberを混ぜることはできない)
- 割り算と剰余の計算結果はゼロ方向へ丸められる
- ビット演算子「>>>」はサポートされません
- 単項演算子「+」はサポートされません
また、NumberとBigIntを比較した際、数値は同じでも、厳密に等しくはありません。厳密な等価演算子(=== と !==)を使用する際は気をつけてください。
11n == 11; // true
11n === 11; // false
BigIntのユーティリティ関数
BigIntには2つのユーティリティ関数があります。
- BigInt.asUintN(width, bigint)
- bigintの値を符号なしwidth-bitの値に収め、結果をBigIntで返します。width-bitから溢れる場合は、溢れた余りを返します。
- BigInt.asIntN(width, bigint)
- bigintの値を符号ありwidth-bitの値に収め、結果をBigIntで返します。width-bitから溢れる場合は、溢れた余りを符号付きで返します。
これらを使えば、たとえばBigIntを64bitの範囲内に収めることなどが可能です。
const unsigned = BigInt.asUintN(64, 123456789n);
const signed = BigInt.asIntN(64, 123456789n);
BigIntとTypedArray
BigIntの追加に伴い、TypedArrayやDataViewにも型やメソッドが追加されています。追加されたのは以下のものです:
- BigUint64Array
- BigInt64Array
- DataView.prototype.getBigInt64
- DataView.prototype.getBigUint64
実際に使ってみる
それでは実際にBigIntを使ってみましょう。まずNumber型の最大整数値を超える値を扱ってみましょう。
const max = Number.MAX_SAFE_INTEGER; // 9007199254740991
const num = max + 8; // 9007199254741000
const bi = BigInt(max) + 8n; // 9007199254740999n
Numberだと少し値がずれているのに対して、BigIntでは正確に計算できていますね。
次に非常に大きな数同士の掛け算を試してみましょう:
const num = 2147483647 * 67280421310721; // 1.4448360452804365e+23
const bi = 2147483647n * 67280421310721n; // 144483604528043653279487n
こちらでもNumberでは不十分なところを、BigIntは正確に表せていますね。
と、こんなふうにBigIntを用いることで、非常に大きな整数値を扱うことができるようになります。