Subterranean Flower

JavaScriptのBigIntで任意精度の整数値を扱う

Author
古都こと
ふよんとえんよぷよぐやま!!!

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を用いることで、非常に大きな整数値を扱うことができるようになります。