JavaScript/BigInt


BigInt は、任意精度の整数を表現するためのプリミティブ型です。BigIntオブジェクトは、BigIntプリミティブ値をラップするオブジェクトです[1]

構文

編集
const bigIntLiteral = 123n;
const bigIntConstructor = BigInt(123);
  • リテラル表記: 数値の後に n を付けることで BigInt リテラルを作成できます。
  • コンストラクタ: BigInt() 関数を使用して BigInt 値を作成できます。

静的プロパティ

編集
BigInt.length
BigInt.name
BigInt.prototype

静的メソッド

編集
BigInt.asIntN(width, bigint)
bigint を 2width で割った剰余の値の符号つき整数を返す。
BigInt.asUintN(width, bigint)
bigint を 2width で割った剰余の値の符号なし整数を返す。

インスタンスプロパティ

編集
BigInt.prototype [ Symbol.toStringTag ]
"BigInt"

インスタンスメソッド

編集
BigInt.prototype.constructor
BigInt.prototype.toLocaleString
BigInt.prototype.toString
BigInt.prototype.valueOf

BigInt の基本的な使用方法

編集

以下のプログラムは、BigInt の基本的な使用方法を示しています。

const bigInt1 = 1234567890123456789012345n;
const bigInt2 = BigInt("9876543210987654321098765");

console.log(bigInt1); // 1234567890123456789012345n
console.log(typeof bigInt1); // bigint

console.log(bigInt1 + bigInt2); // 11111111101111111110111110n

このプログラムでは、BigInt リテラル構文と BigInt コンストラクタを使用して BigInt 値を作成し、それらの加算を行っています。

BigInt と Number の相互変換

編集

以下のプログラムは、BigInt と Number 型の間の変換方法を示しています。

const bigInt = 123456789n;
const number = Number(bigInt);
console.log(number); // 123456789

const bigFromNumber = BigInt(9007199254740991); // MAX_SAFE_INTEGER
console.log(bigFromNumber); // 9007199254740991n

// 精度が失われる可能性がある変換
const hugeNumber = BigInt(Number.MAX_VALUE);
console.log(Number(hugeNumber)); // 1.7976931348623157e+308

このプログラムでは、BigInt から Number への変換、および Number から BigInt への変換を示しています。ただし、大きな値では精度が失われる可能性があることに注意してください。

BigInt の算術演算

編集

以下のプログラムは、BigInt での算術演算の例を示しています。

const a = 1234567890123456789n;
const b = 9876543210987654321n;

console.log(a + b);  // 11111111101111111110n
console.log(a - b);  // -8641975320864197532n
console.log(a * b);  // 12193263111263526900609672107023853369n
console.log(a / b);  // 0n (小数部は切り捨て)
console.log(a % b);  // 1234567890123456789n
console.log(a ** 3n); // 1881676377434183981909562699940347954574863968n

このプログラムでは、BigInt での加算、減算、乗算、除算、剰余、冪乗などの基本的な算術演算を示しています。

注意点

編集
  • 型の混合: BigInt と Number を直接混合して演算することはできません。明示的な変換が必要です。
  • 丸め: BigInt の除算では、結果は常に整数に切り捨てられます。
  • プロトタイプメソッド: BigInt.prototype には、valueOf()、toString()、toLocaleString() などのメソッドがあります。
  • JSON化: BigInt 値は、標準の JSON.stringify() ではシリアライズされません。カスタムシリアライズが必要です。
  • ビット演算子: BigInt は多くのビット演算子(&, |, ^, <<, >>, ~)をサポートしていますが、>>>(符号なし右シフト)は使用できません。

附録

編集

Object.defineProperties()を使用してBigInt.prototypeabssignpowsqrtなどのpolyfillを実装する例を示します。

if (typeof BigInt !== 'undefined') {
  Object.defineProperties(BigInt.prototype, {
    abs: {
      value: function () {
        return this < 0n ? -this : this;
      },
      writable: true,
      enumerable: false,
      configurable: true,
    },
    sign: {
      value: function () {
        return this === 0n ? 0n : this < 0n ? -1n : 1n;
      },
      writable: true,
      enumerable: false,
      configurable: true,
    },
    pow: {
      value: function (exponent) {
        if (exponent < 0n) {
          throw new RangeError('Exponent must be non-negative');
        }
        if (exponent === 0n) {
          return 1n;
        }
        if (exponent === 1n) {
          return this;
        }
        let result = 1n;
        let base = this;
        while (exponent > 0n) {
          if (exponent % 2n === 1n) {
            result *= base;
          }
          base *= base;
          exponent /= 2n;
        }
        return result;
      },
      writable: true,
      enumerable: false,
      configurable: true,
    },
    sqrt: {
      value: function () {
        if (this < 0n) {
          throw new RangeError('Cannot calculate square root of a negative BigInt');
        }
        if (this < 2n) {
          return this;
        }
        const newtonStep = (n, x) => (x + n / x) >> 1n;
        const initialGuess = (this >> (BigInt(this.toString(16).length) - 1n)) + 1n;
        let x0 = initialGuess;
        let x1 = newtonStep(this, x0);
        while (x1 < x0) {
          x0 = x1;
          x1 = newtonStep(this, x0);
        }
        return x0;
      },
      writable: true,
      enumerable: false,
      configurable: true,
    },
    gcd: {
      value: function (other) {
        if (typeof other !== 'bigint') {
          throw new TypeError('Argument must be a BigInt');
        }
        let a = this.abs();
        let b = other.abs();
        if (b === 0n) {
          return a;
        }
        let r;
        while ((r = a % b) !== 0n) {
          a = b;
          b = r;
        }
        return b;
      },
      writable: true,
      enumerable: false,
      configurable: true,
    },
    lcm: {
      value: function (other) {
        if (typeof other !== 'bigint') {
          throw new TypeError('Argument must be a BigInt');
        }
        if (this === 0n || other === 0n) {
          return 0n;
        }
        return (this / this.gcd(other)) * other;
      },
      writable: true,
      enumerable: false,
      configurable: true,
    },
  });
}


// 使用例
if (typeof BigInt !== 'undefined') {
  const bigIntValue = -123n;
  console.log(bigIntValue.abs()); // 123n
  console.log(bigIntValue.sign()); // -1n
  console.log(2n.pow(10n)); // 1024n
  console.log(25n.sqrt()); // 5n
  console.log(26n.sqrt()); // 5n
  console.log(12n.gcd(18n)); // 6n
  console.log(12n.lcm(18n)); // 36n
}
解説
  1. ; Object.defineProperties()の使用
    • Object.defineProperties(BigInt.prototype, { ... })を使用して、BigInt.prototypeに複数のプロパティ(メソッド)を一度に追加しています。
  2. ; 各メソッドの実装
    • abs(): 絶対値を返すメソッド。
    • sign(): 符号を返すメソッド(-1n、0n、1n)。
    • pow(): べき乗を計算するメソッド。
    • sqrt(): 平方根を計算するメソッド(ニュートン法を使用)。
    • gcd(other): 2つのBigIntの最大公約数(GCD)を返すメソッド。
    • lcm(other): 2つのBigIntの最小公倍数(LCM)を返すメソッド。
    プロパティの属性
    • writable: true: メソッドを上書き可能にします。
    • enumerable: false: for...inループで列挙されないようにします。
    • configurable: true: メソッドの削除や属性の変更を可能にします。
    使用例
    • 実装したメソッドの使用例を示しています。
注意点
  • sqrt()メソッドは、ニュートン法を使用しているため、近似値を返します。
  • pow()メソッドは、負の指数をサポートしていません。
  • gcd(other)メソッドは、ユークリッドの互除法を使用して実装している。
    • 引数otherBigInt型でない場合は、TypeErrorをスロー。
  • lcm(other)メソッドは、 GCDを使用してLCMを計算。
    • 引数otherBigInt型でない場合は、TypeErrorをスロー。
    • どちらかの値が0nの場合0nを返す。
  • これらのpolyfillは、すべてのエッジケースを網羅しているわけではありません。必要に応じて、テストを追加し、実装を改善してください。
  • BigIntが実装されていない環境では、これらのpolyfillは動作しません。

脚註

編集
  1. ^ BigIntは、Number型で表現できる範囲を超える整数値を扱うために導入されました。

外部リンク

編集

下位階層のページ

編集