Docs

README

8.3 BigInt

Overview

BigInt is a built-in JavaScript primitive that provides a way to represent integers larger than the Number.MAX_SAFE_INTEGER (2^53 - 1). Introduced in ES2020, BigInt enables precise arithmetic operations on arbitrarily large integers without losing precision.

Learning Objectives

  • Understand the limitations of JavaScript Number type
  • Create and work with BigInt values
  • Perform arithmetic operations with BigInt
  • Convert between Number and BigInt
  • Use BigInt in practical applications

Why BigInt?

Number Limitations

// Safe integer range
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991

// Loss of precision beyond safe range
console.log(9007199254740991 + 1); // 9007199254740992 ✓
console.log(9007199254740991 + 2); // 9007199254740992 ✗ (should be 9007199254740993)
console.log(9007199254740991 + 3); // 9007199254740994 ✗ (should be 9007199254740994)

// Check if safe
console.log(Number.isSafeInteger(9007199254740991)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false

Creating BigInt Values

Literal Syntax

// Append 'n' to create BigInt literal
const big = 123456789012345678901234567890n;
console.log(big); // 123456789012345678901234567890n
console.log(typeof big); // "bigint"

// Negative BigInt
const negative = -9007199254740993n;

BigInt Constructor

// From integer
const fromInt = BigInt(123); // 123n

// From string (for very large numbers)
const fromString = BigInt('123456789012345678901234567890');

// From hex, octal, binary strings
const fromHex = BigInt('0xFF'); // 255n
const fromOctal = BigInt('0o777'); // 511n
const fromBinary = BigInt('0b11111111'); // 255n

Important Restrictions

// Cannot create from decimal/float
BigInt(1.5); // TypeError
BigInt(NaN); // TypeError
BigInt(Infinity); // TypeError

// Use Math.trunc for decimals
BigInt(Math.trunc(1.9)); // 1n

Arithmetic Operations

Basic Operations

const a = 10n;
const b = 3n;

console.log(a + b); // 13n  (addition)
console.log(a - b); // 7n   (subtraction)
console.log(a * b); // 30n  (multiplication)
console.log(a / b); // 3n   (division - truncated)
console.log(a % b); // 1n   (remainder)
console.log(a ** b); // 1000n (exponentiation)

Division Behavior

// Division truncates toward zero
console.log(5n / 2n); // 2n (not 2.5)
console.log(-5n / 2n); // -2n (not -2.5)

// For decimal results, convert to Number
const result = Number(5n) / Number(2n); // 2.5

Unary Operations

const x = 5n;

console.log(-x); // -5n (negation works)
// console.log(+x);   // TypeError (unary + not supported)

Comparison Operations

Equality

// Strict equality (type matters)
console.log(10n === 10); // false (different types)
console.log(10n === 10n); // true

// Loose equality (type coercion)
console.log(10n == 10); // true
console.log(10n == '10'); // true

Relational Comparisons

console.log(10n > 5n); // true
console.log(10n > 5); // true (mixed comparison allowed)
console.log(10n < 20); // true

// Sorting
const mixed = [10n, 5, 8n, 3, 12n];
mixed.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
console.log(mixed); // [3, 5, 8n, 10n, 12n]

Type Conversion

BigInt to Other Types

const big = 123n;

// To Number (may lose precision)
console.log(Number(big)); // 123

// To String
console.log(String(big)); // "123"
console.log(big.toString()); // "123"
console.log(big.toString(16)); // "7b" (hex)
console.log(big.toString(2)); // "1111011" (binary)

// To Boolean
console.log(Boolean(0n)); // false
console.log(Boolean(1n)); // true

Number to BigInt

// Safe integer
const num = 123;
const big = BigInt(num); // 123n

// Precision loss warning
const unsafe = 9007199254740993; // Already lost precision
console.log(BigInt(unsafe)); // 9007199254740992n (wrong!)

// Use string for large numbers
const correct = BigInt('9007199254740993'); // Correct!

Cannot Mix with Number

const big = 10n;
const num = 5;

// These throw TypeError
// big + num;
// big * num;
// Math.sqrt(big);

// Must convert explicitly
console.log(big + BigInt(num)); // 15n
console.log(Number(big) + num); // 15

BigInt with Built-in Objects

Array Methods

const bigInts = [10n, 5n, 20n, 15n];

// Some methods work
console.log(bigInts.includes(5n)); // true

// Sorting requires custom comparator
bigInts.sort((a, b) => {
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
});

JSON

// BigInt is not JSON-serializable by default
const obj = { id: 123456789012345678901n };

// JSON.stringify(obj);  // TypeError

// Custom serialization
const jsonString = JSON.stringify(obj, (key, value) =>
  typeof value === 'bigint' ? value.toString() : value
);
console.log(jsonString); // {"id":"123456789012345678901"}

// Custom parsing
const parsed = JSON.parse(jsonString, (key, value) =>
  key === 'id' ? BigInt(value) : value
);

Bitwise Operations

const a = 0b1010n; // 10n
const b = 0b1100n; // 12n

console.log(a & b); // 8n  (0b1000) - AND
console.log(a | b); // 14n (0b1110) - OR
console.log(a ^ b); // 6n  (0b0110) - XOR
console.log(~a); // -11n - NOT

// Shifts
console.log(a << 2n); // 40n  (left shift)
console.log(a >> 1n); // 5n   (right shift)

Practical Use Cases

Database IDs

// Many databases use 64-bit IDs
const twitterId = 1234567890123456789n;
const snowflakeId = BigInt('1309881276729737216');

// Safe to compare and manipulate
const nextId = snowflakeId + 1n;

Cryptography

// Large prime numbers
const prime = 104729n;
const modulo = 2n ** 256n - 1n;

// Modular exponentiation
function modPow(base, exponent, mod) {
  let result = 1n;
  base = base % mod;
  while (exponent > 0n) {
    if (exponent % 2n === 1n) {
      result = (result * base) % mod;
    }
    exponent = exponent / 2n;
    base = (base * base) % mod;
  }
  return result;
}

Financial Calculations

// Store amounts in cents/smallest unit as BigInt
class Money {
  constructor(cents) {
    this.cents = BigInt(cents);
  }

  add(other) {
    return new Money(this.cents + other.cents);
  }

  multiply(factor) {
    return new Money(this.cents * BigInt(factor));
  }

  toString() {
    const str = this.cents.toString().padStart(3, '0');
    return `$${str.slice(0, -2)}.${str.slice(-2)}`;
  }
}

const price = new Money(9999); // $99.99
const quantity = 1000000;
const total = price.multiply(quantity);
console.log(total.toString()); // Precise calculation

High-Precision Timestamps

// Nanosecond timestamps
const timestampNs = 1234567890123456789n;

// Convert to components
const seconds = timestampNs / 1000000000n;
const nanos = timestampNs % 1000000000n;

Best Practices

  1. Use String for Large Literals: When creating BigInt from large values, use strings to avoid precision loss
  2. Be Explicit About Conversions: Always explicitly convert between Number and BigInt
  3. Handle JSON Serialization: Implement custom serialization for BigInt values
  4. Consider Performance: BigInt operations are slower than Number operations
  5. Use for Integer-Only Operations: BigInt doesn't support decimals

Browser/Node.js Support

BigInt is supported in:

  • Chrome 67+
  • Firefox 68+
  • Safari 14+
  • Node.js 10.4+

Summary

| Feature | Description | | ---------- | ------------------------------------------ | ----------------------- | | Creation | 123n or BigInt(123) | | Arithmetic | +, -, *, / (truncated), %, ** | | Comparison | <, >, <=, >=, ==, === | | Bitwise | &, |, ^, ~, <<, >> | | No mixing | Cannot mix with Number in operations | | No Math | Math object methods don't work with BigInt | | JSON | Requires custom serialization |

Resources

README - JavaScript Tutorial | DeepML