コンテンツにスキップ

JavaScript/長整数

出典: フリー教科書『ウィキブックス(Wikibooks)』
長整数(Big integer)は多倍長整数の一種で、精度を失うことなく数型の範囲を超える大きな整数を扱うことができます。JavaScriptでは、BigIntがプリミティブ長整数に対応するラッパーオブジェクトとして提供されています。

概要

[編集]

JavaScriptでは、数値を扱うための基本オブジェクトとしてNumberがサポートされています。NumberはIEEE 754規格に基づく倍精度64ビット浮動小数点数を採用しており、整数の精度は仮数部に依存しています。また、ビット操作では32ビットの範囲に制限されています。

このような制限を克服するため、任意長演算をサポートするBigIntが導入されました。これにより、大きな整数や高精度な演算が可能になり、より広範なユースケースに対応できます。

長整数リテラル

[編集]

長整数リテラルは、整数リテラルの末尾に'n'を付けた形式で表します。

  • 42n
  • -1n
  • 0n
  • 864e5n(エラー: 指数表記はサポートされません)
  • 0xFFFFn
  • 0b1101n
  • 0o3162n
  • 1_234_567n
  • 2_3_5_7_11n

ただし、単項演算子+はNumber型への暗黙的な型変換を引き起こすため、エラーが発生します。

+1024n; // TypeError: Cannot convert a BigInt value to a number

型と型変換

[編集]

typeof演算子を使用すると、BigInt型の値には文字列"bigint"が返されます。

typeof 999999n; // "bigint"

BigInt()はコンストラクタではないため、new BigInt()はエラーとなります。代わりに、以下のように直接呼び出します。

BigInt("123"); // "bigint"

演算子

[編集]

算術演算子

[編集]

長整数では、+、*、-、**、および%といった算術演算子を使用できます。ただし、長整数とNumber型を混在させた演算はエラーとなります。

1 + 1n; // TypeError
2n + 8; // TypeError

ゼロ除算はRangeErrorを発生させ、try-catchで処理しない限りプログラムは停止します。

1n / 0n; // RangeError
9n % 0n; // RangeError
0n / 0n; // RangeError

ビット操作演算子

[編集]

長整数は数値と同様にビット操作演算子を使用できます。ただし、>>>(論理右シフト)は使用できません。

1n >> 1n; // 0n
1n >>> 1n; // TypeError: BigInts have no unsigned right shift, use >> instead

比較演算子

[編集]

長整数とNumber型の間での比較演算子(==!=)は型が異なっていても動作します。

1n == 1; // true
10n != "10"; // false

一方、厳密比較演算子(===!==)では型が異なる場合は不一致となります。

1n === 1; // false
10n !== "10"; // true

使用例

[編集]

以下は、多倍長整数演算を活用した例です。

円周率を77桁求める
let k = 2n, a = 4n, b = 1n, a1 = 12n, b1 = 4n;
let result = "";

for (let i = 0; i < 100; i++) {
  let p = k * k, q = 2n * k + 1n;
  k += 1n;
  [a, b, a1, b1] = [a1, b1, p * a + q * a1, p * b + q * b1];
  let d = a / b;
  let d1 = a1 / b1;

  while (d === d1) {
    result += Number(d).toString();
    [a, a1] = [10n * (a % b), 10n * (a1 % b1)];
    [d, d1] = [a / b, a1 / b1];
  }
}

console.log(result.length); // 77
console.log(result);               // 31415926535897932384626433832795028841971693993751058209749445923078164062862
console.log(Math.PI.toFixed(77)); // 3.14159265358979311599796346854418516159057617187500000000000000000000000000000

この例では、全ての定数をBigIntリテラル(例: 12n)で記述しなければTypeErrorとなるため、誤りを見つけやすくなっています。また、結果はMath.PIとは一致しませんが、BigIntによる計算結果の方が高精度です。