UNB/ CS/ David Bremner/ teaching/ cs2613/ books/ mdn/ Reference/ Global Objects/ BigInt

BigInt values represent numeric values which are too large to be represented by the number .

Description

A BigInt value, also sometimes just called a BigInt, is a bigint , created by appending n to the end of an integer literal, or by calling the BigInt() function (without the new operator) and giving it an integer value or string value.

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 values are similar to Number values in some ways, but also differ in a few key matters: A BigInt value cannot be used with methods in the built-in Math object and cannot be mixed with a Number value in operations; they must be coerced to the same type. Be careful coercing values back and forth, however, as the precision of a BigInt value may be lost when it is coerced to a Number value.

Type information

When tested against typeof, a BigInt value (bigint primitive) will give "bigint":

typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true

A BigInt value can also be wrapped in an Object:

typeof Object(1n) === "object"; // true

Operators

Most operators support BigInts, however most do not permit operands to be of mixed types — both operands must be BigInt or neither:

The boolean-returning operators allow mixing numbers and BigInts as operands:

A couple of operators do not support BigInt at all:

Special cases:

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
const expected = 4n / 2n; // 2n
const truncated = 5n / 2n; // 2n, not 2.5n

Comparisons

A BigInt value is not strictly equal to a Number value, but it is loosely so:

0n === 0; // false
0n == 0; // true

A Number value and a BigInt value may be compared as usual:

1n < 2; // true
2n > 1; // true
2 > 2; // false
2n > 2; // false
2n >= 2; // true

BigInt values and Number values may be mixed in arrays and sorted:

const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
// [4n, 6, -12n, 10, 4, 0, 0n]

mixed.sort(); // default sorting behavior
// [ -12n, 0, 0n, 10, 4n, 4, 6 ]

mixed.sort((a, b) => a - b);
// won't work since subtraction will not work with mixed types
// TypeError: can't convert BigInt value to Number value

// sort with an appropriate numeric comparator
mixed.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
// [ -12n, 0, 0n, 4n, 4, 6, 10 ]

Note that comparisons with Object-wrapped BigInt values act as with other objects, only indicating equality when the same object instance is compared:

Object(0n) === 0n; // false
Object(0n) === Object(0n); // false

const o = Object(0n);
o === o; // true

Because coercing between Number values and BigInt values can lead to loss of precision, the following are recommended:

Conditionals

A BigInt value follows the same conversion rules as Numbers when:

Namely, only 0n is falsy; everything else is truthy.

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

Cryptography

The operations supported on BigInt values are not constant-time and are thus open to timing attacks. JavaScript BigInts therefore could be dangerous for use in cryptography without mitigating factors. As a very generic example, an attacker could measure the time difference between 101n ** 65537n and 17n ** 9999n, and deduce the magnitude of secrets, such as private keys, based on the time elapsed. If you still have to use BigInts, take a look at the Timing attack FAQ for general advice regarding the issue.

Use within JSON

Using JSON.stringify() with any BigInt value will raise a TypeError, as BigInt values aren't serialized in JSON by default. However, JSON.stringify() specifically leaves a backdoor for BigInt values: it would try to call the BigInt's toJSON() method. (It doesn't do so for any other primitive values.) Therefore, you can implement your own toJSON() method (which is one of the few cases where patching built-in objects is not explicitly discouraged):

BigInt.prototype.toJSON = function () {
  return this.toString();
};

Instead of throwing, JSON.stringify() now produces a string like this:

console.log(JSON.stringify({ a: 1n }));
// {"a":"1"}

If you do not wish to patch BigInt.prototype, you can use the replacer parameter of JSON.stringify to serialize BigInt values:

const replacer = (key, value) =>
  typeof value === "bigint" ? value.toString() : value;

const data = {
  number: 1,
  big: 18014398509481982n,
};
const stringified = JSON.stringify(data, replacer);

console.log(stringified);
// {"number":1,"big":"18014398509481982"}

If you have JSON data containing values you know will be large integers, you can use the reviver parameter of JSON.parse to handle them:

const reviver = (key, value) => (key === "big" ? BigInt(value) : value);

const payload = '{"number":1,"big":"18014398509481982"}';
const parsed = JSON.parse(payload, reviver);

console.log(parsed);
// { number: 1, big: 18014398509481982n }

Note: While it's possible to make the replacer of JSON.stringify() generic and properly serialize BigInt values for all objects, the reviver of JSON.parse() must be specific to the payload shape you expect, because the serialization is lossy: it's not possible to distinguish between a string that represents a BigInt and a normal string.

BigInt coercion

Many built-in operations that expect BigInts first coerce their arguments to BigInts. The operation can be summarized as follows:

The best way to achieve nearly the same effect in JavaScript is through the BigInt() function: BigInt(x) uses the same algorithm to convert x, except that Numbers don't throw a TypeError, but are converted to BigInts if they are integers.

Note that built-in operations expecting BigInts often truncate the BigInt to a fixed width after coercion. This includes BigInt.asIntN, BigInt.asUintN, and methods of BigInt64Array and BigUint64Array.

Constructor

Static methods

Instance properties

These properties are defined on BigInt.prototype and shared by all BigInt instances.

Instance methods

Examples

Calculating Primes

// Returns true if the passed BigInt value is a prime number
function isPrime(p) {
  for (let i = 2n; i * i <= p; i++) {
    if (p % i === 0n) return false;
  }
  return true;
}

// Takes a BigInt value as an argument, returns nth prime number as a BigInt value
function nthPrime(nth) {
  let maybePrime = 2n;
  let prime = 0n;

  while (nth >= 0n) {
    if (isPrime(maybePrime)) {
      nth--;
      prime = maybePrime;
    }
    maybePrime++;
  }

  return prime;
}

nthPrime(20n);
// 73n

Specifications

Browser compatibility

See also