BigInt, arbitrary precision integers in JavaScript

Published: September 03, 2018  •  javascript

The Chrome browser introduced with version 67 (end of May 2018) a new feature to the JavaScript language:
The numeric primitive type: BigInt

BigInt is a primitive that can represent integers with arbitrary precision, unlike the Number primitive that can only safely store integer values up to 2^53. BigInts allow an application to work with numbers that would not fit into a Number. An application never has to worry about overflow errors when it performs integer arithmetic with BigInt.

For example, with a BigInt, an application can represent the following number with 949 digits.


One of the application that depends on big number arithmetic is cryptography.
If you use a back end language that supports a 64-bit datatype like Java with long, BigInts allow a JavaScript application to safely represent these values on the client (for example primary keys, timestamps in nanoseconds).

Implementations and Standard

Chrome supports BigInt since version 67.

Apple is working on the BigInt support and it looks like it will be part of Safari 12.

Mozilla works on an implementation too. You can track the progress here:

I don't know the current state of the implementation in Microsoft's Edge browser.

BigInt is at the time of writing this blog post (September 2018) not a ECMAScript standard. The proposal is in stage 3 and only proposals in stage 4 will be part of the next ECMAScript standard. One of the requirement for a proposal to move from 3 to 4 is that there must be two implementations by two independent VMs and they must pass the acceptance tests. With 3 browser implementations in the near future my guess is that there is a good chance that BigInt will be part of ECMAScript 2019 or 2020.

You can track all the JavaScript proposals in this GitHub repository:

The just released version 7 of Babel supports BigInt and the upcoming 3.1 version of TypeScript introduces BigInts to TypeScript.


To differentiate a BigInt from a Number you have to append the letter n to the end of the number. For example 156 is a Number, 156n is a BigInt.

You can convert a Number to a BigInt with the global BigInt(number) function.

const aBigInt = 11n;

const aNumber = 156;
const aBigInt = BigInt(aNumber);
aBigInt === 156n // true

BigInts can also be written with binary, octal or hexadecimal notation

const h = 0x100n;
// h === 256n

const o = 0o064n;
// o === 52n

const b = 0b10101010101n;
// b === 1365n

When used as a boolean, BigInt follows the same rule as a Number. 0n is falsy.

if (0n) {
} else {
// prints "falsy"

The typeof operator used with a BigInt returns "bigint"

typeof 156;
// "number"
typeof 156n;
// "bigint"


BigInts support the same operators that you can use with Numbers and work as expected.

20 - 3 * 4 ** 2 / (3 % 4) === 4
20n - 3n * 4n ** 2n / (3n % 4n) === 4n

/ and % rounds towards zero

6n / 7n === 0n
7n / 6n === 1n

Most bitwise operators also work like they do with Numbers

128 << 3
// 1024
128n << 3n
// 1024n

Not supported is the >>> operator, because BigInts are signed. To get an unsigned shift, pass in a positive BigInt to >>

128n >>> 3n
// Uncaught TypeError: BigInts have no unsigned right shift, use >> instead

The Unary - operator can be used for denoting a negative BigInt

const a = -156n

The unary + operator is not supported with BigInts, because it would cause a problem with asm.js which expects the unary + operator to always return a Number.

const b = +6
b === 6

const c = +6n
// Uncaught TypeError: Cannot convert a BigInt value to a number

There is one limitation you need to be aware of. You cannot mix Number and BigInt. The JavaScript engines throws an exception if you try to do that.

const d = 45 + 10n
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

The JavaScript engine cannot implicit convert Number and BigInt because BigInt does not support fractions and Number can only represent integers safely up to 2^53.

Conversion to and from Number

You can always explicitly convert with the global functions BigInt() and Number()

BigInt(45) + 10n === 55n
45 + Number(10n) === 55

parseFloat() and parseInt() can also convert a BigInt to a Number.

const a = parseFloat(100n);
// a === 100

const b = parseInt(101n);
// b === 101

You need to be cautious with conversions to Number. If you convert a BigInt that is outside the safe integer range (2^53), Number(), parseFloat() and parseInt() do not throw an error, but the Number they return is not able to represent the integer correctly.
If the BigInt is greater than Number.MAX_VALUE these three methods return Infinity.

const bi = 2n**56n;
// bi === 72057594037927936n

const n = Number(72057594037927936n);
// n === 72057594037927940  

const large = 2n*10n**309n;
Number(large) === Infinity;
parseFloat(large) === Infinity;


As mentioned before you cannot mix Numbers and BigInts. There is one exception to this rule: comparison operators. The precision does not matter here because these operators resolve to a boolean value.

10 == 10n
// true

10 === 10n
// false

9 < 10n
// true

9n > 10
// false

Conversion to and from strings

The global BigInt() function cannot only convert Numbers to BigInts but also strings to BigInts

BigInt(10) === 10n;
BigInt('100') === 100n;

The function throws an exception if it cannot convert the provided value into a BigInt.

// RangeError: The number 23.5 cannot be converted to a BigInt because it is not an integer

// SyntaxError: Cannot convert 23.5 to a BigInt

BigInts also have a toString() method that convert the number to a string

const s = 100n.toString();
// s === "100"

The + operator can be used to concatenate strings and BigInts. Same behaviour that we already know when concatenating strings and Numbers.

const s1 = 'Amount: ' + 1;
// s1 === "Amount: 1"

const s2 = 'Amount: ' + 1n;
// s2 === "Amount: 1"

You can also use BigInts in template literals. Same behaviour that you already know from Numbers.

const value = 123n;
const s3 = `Amount: ${value}`
// s3 === "Amount: 123"


JSON does not support BigInt. If you try to convert a JavaScript object with a BigInt field to JSON the JavaScript VM throws an exception.

const obj = {name: 'test', value: 100n};
const j = JSON.stringify(obj);
// TypeError: Do not know how to serialize a BigInt

As a workaround you can convert BigInts to either Numbers (if they fit into the supported range) or to a string. JSON.stringify() supports a second parameter called a replacer, which we can use for writing a generic function that converts all BigInts to strings.

const j = JSON.stringify(obj, (key, value) => {
	if (typeof value === 'bigint') {
		return value.toString() + 'n';
	} else {
		return value;

// j === "{"name":"test","value":"100n"}"

To parse such a JSON we can pass a function as second parameter (receiver) to the JSON.parse() method. This function is called for each key/value pair. It first checks if the value is a string, contains only digits and ends with the letter n. If true, it passes the string to the BigInt constructor else it returns the original value.

const obj2 = JSON.parse(j, (key, value) => {
  if (typeof value === 'string' && /^\d+n$/.test(value)) {
    return BigInt(value.slice(0, -1));
  return value;

// obj2 --> {name: "test", value: 100n}


For Numbers, the JavaScript VM provides a built-in Math object that has properties and methods for mathematical constants and functions. For BigInts there is no such object implemented. I guess a lot of the provided Math methods don't make sense for a number type without fraction, but there are a few methods that could be useful even for BigInts. Fortunately these are not that complicated to implement. Here a very trivial implementation of max, min, sign, abs and sqrt.

class BigIntMath {

	static max(...values) {
		if (values.length === 0) {
			return null;

		if (values.length === 1) {
			return values[0];

		let max = values[0];
		for (let i = 1; i < values.length; i++) {
			if (values[i] > max) {
				max = values[i];
		return max;

	static min(...values) {
		if (values.length === 0) {
			return null;

		if (values.length === 1) {
			return values[0];

		let min = values[0];
		for (let i = 1; i < values.length; i++) {
			if (values[i] < min) {
				min = values[i];
		return min;

	static sign(value) {
		if (value > 0) {
			return 1n;
		if (value < 0) {
			return -1n;
		return 0n;

	static abs(value) {
		if (this.sign(value) === -1n) {
			return -value;

	static sqrt(value) {
		if (value < 0n) {
			throw 'square root of negative numbers is not supported'

		if (value < 2n) {
			return value;

		function newtonIteration(n, x0) {
			const x1 = ((n / x0) + x0) >> 1n;
			if (x0 === x1 || x0 === (x1 - 1n)) {
				return x0;
			return newtonIteration(n, x1);

		return newtonIteration(value, 1n);



const min = BigIntMath.min(1n,2n,3n,4n); // min == 1n
const max = BigIntMath.max(1n,2n,3n,4n); // min == 4n
const sign = BigIntMath.sign(-11n); // sign === -1n
const abs = BigIntMath.abs(-11n); // abs === 11n
const sqrt = BigIntMath.sqrt(81n); // sqrt === 9n

There is no need for a Math.pow() implementation, we can use the exponentiation operator introduced in ECMAScript 2016.

const a = Math.pow(3,4);
// a === 81

const b = 3n ** 4n;
// b === 81n


Because BigInt is a primitive there is no way for a polyfill to implement the n syntax and add BigInt support to the built-in operators in a browser that doesn't have a BigInt implementation yet or in an older browser that will never get BigInt support.

But there are Big Integer libraries that you can use today. The syntax looks different and is not that convenient as the built in implementation. The performance will also be slower than the native implementation, because all these libraries have to run their calculations in JavaScript.

Google published a chart on their BigInt blog post that compares the native implementation with a few Big Integer libraries:

The following example shows you how you can do big integers arithmetic with the bn.js library.

You add the library like any other JavaScript library

npm install bn.js

Then import it, create BN instances from strings or numbers and then use the provided methods.

import BN from 'bn.js';

const a = new BN('156');
const b = new BN(200);

const result = a.add(b);
// result.toString() === "356"

const b1 = new BN('90071992547409910000');
const b2 = new BN('29839283291982398238');
const r = b1.mul(b2);
// r.toString() === "2687683702295491619562538437047738580000"

The bn.js library provides a wide variety of methods. See the documentation on the GitHub project page:

There are many other libraries that introduce big integer arithmetic to Node.js and the browser.