completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

BigInt

Use JavaScript BigInt for exact whole-number calculations beyond Number.MAX_SAFE_INTEGER, and learn the rules for arithmetic, conversion, and fixed-width wrapping.

By the end, you can
  • 01
    Spot numbers that aren't safeUse Number.MAX_SAFE_INTEGER and Number.isSafeInteger to tell when Number starts rounding whole numbers.
  • 02
    Write exact BigIntsWrite BigInts with the n suffix, do math with them, and change types on purpose so you never mix BigInt and Number by accident.
  • 03
    Fit numbers into a fixed sizeExplain how BigInt.asIntN and BigInt.asUintN make a value fit into 8 or 64 bits.

BigInt in one sentence

BigInt is a JavaScript type for whole numbers that stay exact, however big they get. A whole number, also called an integer, has no decimal part, like 7 or -20.

You write a BigInt like a normal number with an n on the end: 10n. The n is called a suffix, because it goes at the end. It tells JavaScript: "keep every digit of this whole number."

Why do you need it? The Data types lesson listed bigint as one of the eight basic value types. The Numbers lesson showed a problem with the normal Number type:

  • Number is great for everyday math: prices, percentages, decimals, and the Math tools.
  • Number keeps whole numbers exact only up to Number.MAX_SAFE_INTEGER, which is 9007199254740991.
  • Past that, Number starts to skip some whole numbers. It rounds them to a number nearby.

BigInt never skips. Every digit stays exact.

Real-life analogyNumber is a calculator; BigInt is a long strip of paper

A pocket calculator has a screen with room for only so many digits. When a number is too long, the calculator rounds it to fit, and it doesn't warn you. Now picture writing the digits on a strip of paper instead. When you need more room, you add more paper, and every digit stays exact. On this strip you only write whole numbers. There is no decimal point.

In real life: A calculator screen that fits about 16 digits
In JavaScript: Number: fast, but only about 16 exact digits
In real life: A strip of paper you can keep making longer
In JavaScript: BigInt: every digit stays exact, as long as the computer has memory
In real life: The calculator has a decimal point
In JavaScript: Number can hold fractions like 0.5
In real life: You only write whole numbers on the strip
In JavaScript: BigInt has no decimal part

In this lesson you will:

  • see where Number stops being exact,
  • write BigInts with the n suffix,
  • do exact math with BigInts, step by step,
  • fix the common error "Cannot mix BigInt and other types",
  • use BigInt.asIntN and BigInt.asUintN to fit a number into a fixed size.

Number.MAX_SAFE_INTEGER: where Number stops being exact

INTERACTIVE

A safe integer is a whole number that Number stores exactly. With safe integers, adding 1 always gives the next whole number, and two different numbers never look the same.

The largest safe integer is 9007199254740991. JavaScript keeps it in Number.MAX_SAFE_INTEGER, so you don't have to remember the digits. Above it, Number can't store every whole number. Some are rounded to a number next to them.

Try the explorer below. Line 1 saves the largest safe integer as max. Lines 3 to 5 add 1, 2, and 3 to it. Look closely at max + 1 and max + 2: Number prints the same value for both. Line 8 does the same addition with BigInt, and the answer stays exact.

Step past the largest safe integer
Step past the largest safe integerPop out in the code editor (opens in a new tab)JavaScript
const max = Number.MAX_SAFE_INTEGER;console.log(max);console.log(max + 1);console.log(max + 2);console.log(max + 3);console.log(2 ** 53 + 1 === 2 ** 53);console.log(Number.isSafeInteger(max + 1));console.log(BigInt(max) + 1n);
Console outputunsafe
  • 9007199254740991
  • 9007199254740992
  • 9007199254740992
  • 9007199254740994
  • true
  • false
  • 9007199254740992n

Line 6 prints true, because both Number sums are rounded to the same value.

Try it yourself
Add to the largest safe integer:

Number gives 9007199254740992, 9007199254740992, 9007199254740994 for max + 1, max + 2, and max + 3. The BigInt line for +1 is exact: 9007199254740992n.

Number math and BigInt math side by side. Change the amount you add, then watch lines 7 and 8 change.

The code uses three tools you may not know yet:

  • 2 ** 53 means 2 to the power of 53. The ** operator raises a number to a power. Line 6 prints true, because 2 ** 53 + 1 is rounded to the same value as 2 ** 53.
  • Number.isSafeInteger(value) gives true if the value is a safe integer, and false if not. Line 7 uses it.
  • BigInt(max) on line 8 turns the Number max into a BigInt. That is fine here, because max is still exact.
Left, Number: max + 1 and max + 2 both point to one card, ending in 992. Same value. Right, BigInt: adding 1n and 2n gives two different cards, ending in 992n and 993n. Both exact.Numbermax + 1max + 2…992same valueBigInt+ 1n+ 2n…992n…993nboth exact
Each card shows only the last digits; the first digits, 9007199254740, are the same on every card. With Number, max + 1 and max + 2 come out as the same value, so one whole number is lost. With BigInt, adding 1n and 2n gives two different answers, and both are exact.
Real-life analogyA calculator screen that rounds when it runs out of room

A cheap calculator doesn't beep when a number is too long for its screen. It just rounds it. Number does the same above the largest safe integer. It still gives you a value, but some of the whole numbers near it are missing.

In real life: The screen is full
In JavaScript: Number has used up its exact digits
In real life: The calculator rounds without a warning
In JavaScript: max + 2 can come out the same as max + 1
In real life: A warning light would help
In JavaScript: Number.isSafeInteger(value) is your warning light

A simple rule:

  • Use Number for everyday values: counts on a page, loop counters, positions on the screen, percentages, and decimals.
  • Think about BigInt when the value is a whole number, every digit matters, and it might grow past Number.MAX_SAFE_INTEGER.

The n suffix: how to write a BigInt

The easiest way to make a BigInt is to write a whole number with n at the end. A value written straight into your code is called a literal. So 10 is a Number literal, and 10n is a BigInt literal.

The n only works on whole numbers. You can't write 1.5n, because a BigInt has no decimal part.

Write BigInts with nPop out in the code editor (opens in a new tab)JavaScript
const exact = 10n;console.log(typeof exact);console.log(exact + 5n);console.log(Boolean(0n));

Line by line:

  1. Line 1 makes a BigInt, 10n, and saves it as exact.
  2. Line 2 asks for its type with typeof, which gives a value's type as text. It prints bigint.
  3. Line 3 adds 5n. Both sides are BigInts, so this works. It prints 15n.
  4. Line 4 prints false. Boolean(value) tells you whether a value counts as true or false. 0n counts as false, just like the Number 0. A value that counts as false is called falsy.

Every BigInt except 0n counts as true, even -1n.

Three cards. 10 has typeof number. 10n has typeof bigint. 1.5n is a SyntaxError, because a BigInt can't have a decimal part.10"number"a Number10n"bigint"a BigInt1.5nSyntaxErrorno decimals
The only difference between 10 and 10n is the n, but they are different types. The n only works on whole numbers, so 1.5n is an error.
Two ways to make a BigInt

Write the n when you type the number into your code: 123n. Use the BigInt() function when the digits come as text: BigInt("123").

Don't write BigInt(9007199254740993). That number is too big for Number, so it is already rounded before BigInt() sees it.

Turn text digits into a BigIntPop out in the code editor (opens in a new tab)JavaScript
const fromText = BigInt("123");
console.log(fromText);
console.log(fromText + 1n);

Line 1 turns the text "123" into the BigInt 123n. The digits never pass through Number, so none of them can be rounded. Line 2 prints 123n. Line 3 adds 1n and prints 124n, which shows the result really is a BigInt.

A number with a decimal part is refusedPop out in the code editor (opens in a new tab)JavaScript
console.log(BigInt(1.5));

This line throws a RangeError. That is the error JavaScript throws when a value is outside what is allowed. A BigInt can't hold the .5.

BigInt math: exact, with whole numbers only

STEP THROUGH

BigInt works with the math operators you already know:

  • + adds, - subtracts, and * multiplies.
  • ** raises a number to a power.
  • / divides.
  • % gives the remainder: what is left over after dividing.

There is one rule: both values must be BigInts. The values on each side of an operator are called operands. In 7n / 2n, the operands are 7n and 2n.

There is also one surprise: division. A BigInt can't have a decimal part, so division cuts the decimal part off.

Press Step to walk through the replay. Line 1 works out 10n ** 20n, which is 1 followed by 20 zeros, exactly. Then pick other values for lines 2 and 3, and compare 7n / 2n, -7n / 2n, and 25n / 4n.

Step through exact BigInt math
Step 0 of 7Ready
Your turn: follow the blue line

Guess what each console line prints. Then step through and watch JavaScript do the exact BigInt math.

Running in
  1. script
Next: line 1
const a = 7n;const b = 2n;console.log(power);console.log(a / b);console.log(a % b);console.log(typeof 10n);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
Pick the values for lines 2 and 3.

Picking new values starts the replay again, with real BigInt results.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Division cuts off the decimal part

7n / 2n is 3n, not 3.5. -7n / 2n is -3n, not -4n. JavaScript cuts the decimal part off, so the answer always moves toward zero. This is called truncating toward zero.

So BigInt is a good fit for exact whole-number work, such as:

  • factorials, like 5!, which means 1 × 2 × 3 × 4 × 5,
  • counters and IDs that grow very large,
  • hash values, which are long numbers worked out from some data.

BigInt is not for decimals. If your math needs a half, a tenth, or a percentage, use Number.

Mixing with Number: compare freely, change the type on purpose

STEP THROUGH

BigInt and Number are two different types. JavaScript lets you compare one with the other. But it won't do math that mixes them, like 1n + 1. It throws a TypeError instead. A TypeError is the error JavaScript throws when a value has the wrong type for a job.

This error helps you. Without it, JavaScript would have to guess what you wanted: an exact BigInt answer, or a Number answer that can have decimals. So it asks you to choose.

Real-life analogyYou can't add euros to dollars without changing one first

Someone asks you to add 1 euro and 1 dollar. A careful accountant first asks which currency the answer should be in. Then they change one amount into that currency, and add. JavaScript acts like that accountant: change one side first, then add.

In real life: €1 + $1 is unclear
In JavaScript: 1n + 1 is unclear
In real life: Change the dollars into euros first
In JavaScript: Change one side first, with BigInt(1) or Number(1n)
In real life: A bad exchange rate loses money
In JavaScript: Changing a huge BigInt into a Number can lose digits
Left: 1n + 1. A BigInt card plus a Number card gives a TypeError. Right: 1n + BigInt(1). Two BigInt cards add up to 2n.1n + 11n+1BigIntNumberTypeError1n + BigInt(1)1n+1nBigIntBigInt2n
Math needs both sides to be the same type. 1n + 1 mixes a BigInt and a Number, so it throws. Change the Number first with BigInt(1), and both sides are BigInts.

Step through the replay below. It runs seven lines, one at a time:

  • Lines 1 to 3 compare a BigInt with a Number.
  • Lines 4 and 5 change a value from one type to the other, on purpose. Number(value) turns a value into a Number.
  • Lines 6 and 7 throw errors.
Compare, change the type, then see the TypeError
Step 0 of 7Ready
Your turn: follow the blue line

Comparisons, type changes you choose, a rounded value, and two common errors, one line at a time.

Running in
  1. script
Next: line 1
console.log(1n === 1);console.log(2n > 1);console.log(BigInt("123"));console.log(Number(9007199254740993n));console.log(BigInt(1.5));console.log(1n + 1);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The table sums up the replay. Read each row as: "when I write this, I get this result, for this reason."

What happens when BigInt meets Number
When you writeWhat you getWhy
1n == 1true== compares only the amount, and both amounts are 1.
1n === 1false=== also checks the type, and the types are different.
2n > 1trueYou can compare a BigInt with a Number using > and <.
1n + 1TypeErrorMath can't mix a BigInt and a Number.
BigInt(1.5)RangeErrorA BigInt can't hold a decimal part.
Number(9007199254740993n)9007199254740992The huge number is rounded when it becomes a Number.
BigInt and JSON

JSON is the text format that websites use to send data. JSON.stringify(value) turns a value into JSON text. JSON has no BigInt type, so JSON.stringify({ id: 1n }) throws an error.

So servers often send very large IDs as text: "9007199254740993". Keep the ID as text to show it or compare it. Turn it into a BigInt with BigInt(idText) only when you need to do math with it.

A few more things don't work with BigInt:

  • +10n throws. A + in front of a value turns it into a Number, and BigInt refuses.
  • Math.max(1n) throws, because the Math tools only take Numbers.
  • Sorting a list that mixes BigInts and Numbers needs care. You'll see how further down this page.

BigInt.asIntN and BigInt.asUintN: fit a number into a fixed size

INTERACTIVE

Computers store numbers as bits. A bit is a single 0 or 1. With 8 bits you can make 256 different patterns, so 8 bits can count from 0 to 255.

Most of the time in JavaScript, you never choose how many bits a number uses. But some other systems fix the size. For example, a database ID, a hash value, or a file format may say "this number is exactly 64 bits." BigInt has two tools for this:

  • BigInt.asUintN(bits, value) keeps only the given number of bits and reads them as unsigned: zero or positive only.
  • BigInt.asIntN(bits, value) keeps the same bits but reads them as signed: the top half of the patterns stand for negative numbers.
Real-life analogyA car's mileage counter with a fixed number of digits

A car's mileage counter has a fixed number of digit wheels. When every wheel shows 9, the next mile turns them all back to 0. Fixed-size numbers do the same thing with bits.

In real life: A 3-digit counter goes 998, 999, 000
In JavaScript: A fixed-size number starts again at 0 after its largest value
In real life: Read the digits as miles driven
In JavaScript: asUintN reads the bits as zero or positive
In real life: Read the digits as steps forward or back
In JavaScript: asIntN reads the bits so that some of them mean negative numbers

The table shows three calls. Read each row as: "this call gives this result, and here is why."

Three fixed-size BigInt calls
CallResultWhy
BigInt.asUintN(8, 257n)1n8 unsigned bits hold 0 to 255. 257 is 1 more than 256, so the count starts again and lands on 1.
BigInt.asIntN(8, 255n)-1nRead as signed, the 8-bit pattern for 255 means -1.
BigInt.asUintN(64, -1n)18446744073709551615nUnsigned 64 bits can't hold -1, so it goes around to the largest 64-bit value.
BigInt.asUintN(8, 257n). The card 257n goes into a box called 8 bits, which holds 0 to 255. What comes out is the card 1n.BigInt.asUintN(8, 257n)257ntoo big8 bitsholds 0 to 2551nstarts again
8 bits can only hold the numbers 0 to 255. After 255 the count starts again at 0, like a car's mileage counter. So 256 becomes 0, and 257 becomes 1n.
Fit a BigInt into a fixed number of bits
Three fixed-size callsPop out in the code editor (opens in a new tab)JavaScript
console.log(BigInt.asUintN(8, 257n));console.log(BigInt.asIntN(8, 255n));console.log(BigInt.asUintN(64, -1n));
Output of this lineline 1

BigInt.asUintN(8, 257n)

1n

8 unsigned bits hold 0 to 255. After 255 the count starts again at 0, so 257 lands on 1.

Try it yourself
Pick a line:

BigInt.asUintN(8, 257n) returns 1n. 8 unsigned bits hold 0 to 255. After 255 the count starts again at 0, so 257 lands on 1.

Each call keeps only the given number of bits. Use these tools when another system expects a fixed-size number.

You won't need these tools for normal counting. Use them when your code works with another system that uses fixed-size numbers: binary file formats, 64-bit hash values, or database IDs. A later lesson on typed arrays uses them too.

Where you will use BigInt

Most JavaScript math should still use Number. Choose BigInt only when all three of these are true:

  • the value is a whole number,
  • every digit must be exact,
  • the value might grow past Number.MAX_SAFE_INTEGER.
Number, BigInt, or keep it as text?
  • A shop price with cents, like 19.99
  • A science measurement that is only an estimate, like the number of atoms in a spoon of water
  • A 64-bit database ID that might be 9007199254740993
  • A completion percentage such as 82.5%
  • The exact value of 30! (1 × 2 × 3 × … × 30)
  • A normal loop counter from 0 to 100
Try it yourself
0 of 6 correct

Put each value in the best group. Each answer explains why BigInt is not always the right choice.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Here is where BigInt shows up in real code:

  • Large IDs. Servers often send 64-bit IDs as text, so the browser doesn't round them. Turn one into a BigInt only if you need to do math with it.
  • Factorials and counting combinations. Values like 30! are whole numbers that grow very fast.
  • Money counted in cents, at huge sizes. If you store money as whole cents and totals can get enormous, BigInt keeps them exact. It still can't store 19.99 directly.
  • Security code, hash values, and binary data. These often use fixed-size numbers, where asIntN and asUintN matter.
Keep a server ID exactPop out in the code editor (opens in a new tab)JavaScript
const idText = "9007199254740993";
const id = BigInt(idText);
console.log(id + 1n);

Line 1 holds the ID as text. Line 2 turns the text straight into a BigInt, so every digit is kept. Line 3 adds 1n and prints 9007199254740994n.

When not to use BigInt

Don't use BigInt for decimal measurements, percentages, or animation math. Don't use it to make code faster, either. BigInt is exact, but it is often slower than Number.

Common BigInt misconceptions

“BigInt is just a bigger Number.”

It is a different type. That is why typeof 10n is "bigint", and 1n === 1 is false.

“BigInt fixes decimal math.”

A BigInt has no decimal part. It can't hold 0.1, 19.99, or 3.5.

“JavaScript will change the type for me.”

Not for math. 1n + 1 throws. You choose: 1n + BigInt(1) gives 2n, and Number(1n) + 1 gives 2.

“BigInt works everywhere Number works.”

Math.max(1n), +10n, and JSON.stringify on a BigInt all throw.

“If a server sends a huge ID, turn it into a BigInt right away.”

If you only show, store, or compare the ID, keeping it as text is often safest. Turn it into a BigInt only when you need to do math with it.

JSON can't hold a BigIntPop out in the code editor (opens in a new tab)JavaScript
const record = { id: 1n };
console.log(JSON.stringify(record));
Math tools only take NumbersPop out in the code editor (opens in a new tab)JavaScript
console.log(Math.max(1n));

Both blocks above throw a TypeError when you run them.

Sort BigInts and Numbers togetherPop out in the code editor (opens in a new tab)JavaScript
const values = [2n, 10, 1n];
values.sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
console.log(values);

Line by line:

  1. Line 1 makes a list with two BigInts and one Number.
  2. Line 2 sorts the list. .sort() calls your function with two items at a time, left and right. The function gives -1 if left should come first, 1 if right should come first, and 0 if they are equal. The ? : is a short if/else: a ? b : c means "if a, then b, else c".
  3. Line 3 prints [ 1n, 2n, 10 ].

The function uses only < and >, which can compare a BigInt with a Number. The common shortcut left - right would mix the types and throw.

Fun fact

Division and remainder work well together. / tells you how many whole times one number fits into another, and % tells you what is left over. For example, 17n / 5n is 3n, and 17n % 5n is 2n. Programs use this pair to cut a huge number into smaller pieces.

Practice: exact whole numbers

5 EXERCISES
Exercise 1 · Warm-upPredict three BigInt outputs

Read the code. Type the three lines it prints, in order.

Starter codePop out in the code editor (opens in a new tab)JavaScript
console.log(7n / 2n);
console.log(typeof 10n);
console.log(1n === 1);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeFix a mixing TypeError

    The starter code throws an error. Change the fee so both values are BigInts. Then type what the program prints.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const cents = 99n;
    const fee = 1;
    console.log(cents + fee);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · ChallengeWork out 25! exactly

      25! means 1 × 2 × 3 × … × 25. Write a loop that starts with 1n and multiplies by every BigInt from 2n to 25n. Then print the result.

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeTurn an ID from text into a BigInt

        Servers often send large IDs as text. Turn this one into a BigInt and add one, without losing any digits.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const idText = "9007199254740993";
        const id = BigInt(idText);
        console.log(id + 1n);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeFit 260 into 8 bits

          Predict what it prints before you run it.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          console.log(BigInt.asUintN(8, 260n));

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            8 QUESTIONS

            For each code question, first find the type of each value: BigInt or Number. Then work out the answer. Read the explanation for each choice, too.

            Lesson quiz · 8 questionsScore: first tries count
            1. Question 1 of 8Which is the first whole number past Number.MAX_SAFE_INTEGER?

              Choose an answer to see the explanation.

            2. Question 2 of 8What does this comparison print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(2 ** 53 + 1 === 2 ** 53);

              Choose an answer to see the explanation.

            3. Question 3 of 8Which of these is a BigInt literal?

              Choose an answer to see the explanation.

            4. Question 4 of 8What does this BigInt division print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(7n / 2n);

              Choose an answer to see the explanation.

            5. Question 5 of 8What happens when this line runs?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(1n + 1);

              Choose an answer to see the explanation.

            6. Question 6 of 8What do these two comparisons print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(1n == 1);
              console.log(1n === 1);

              Choose an answer to see the explanation.

            7. Question 7 of 8What does this 8-bit call print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(BigInt.asUintN(8, 257n));

              Choose an answer to see the explanation.

            8. Question 8 of 8Which value is falsy, which means it counts as false?

              Choose an answer to see the explanation.

            Key takeaways

            • Number.MAX_SAFE_INTEGER is 9007199254740991. Above it, Number may skip whole numbers.
            • Put n after a whole number to make a BigInt, like 10n. typeof 10n is "bigint".
            • BigInt math is exact for whole numbers. Division cuts off the decimal part, toward zero. 0n is falsy.
            • Math can't mix BigInt and Number. Change one side on purpose. Be careful: a huge BigInt can lose digits when it becomes a Number.
            • BigInt.asIntN and BigInt.asUintN fit a value into a fixed number of bits, signed or unsigned.

            BigInt in one line.
            A BigInt is an exact whole number, written like 10n. Use it when Number's safe range is not big enough.

            Up next: Type conversion. You will learn String(), Number(), and Boolean(), and when JavaScript changes a value's type on its own.

            CompleteFrontend Clear concepts. Working examples.