Skip to main content

decimal.js vs big.js vs bignumber.js: Arbitrary Precision in JavaScript (2026)

·PkgPulse Team

TL;DR

decimal.js is the most feature-rich arbitrary precision library — supports trigonometric functions, logarithms, modular arithmetic, and is the basis for Decimal128 in databases. big.js is the smallest and simplest — 6KB, covers the most common use cases (add, subtract, multiply, divide with configurable precision), no trig. bignumber.js sits between them — same author as big.js and decimal.js, broader base support (binary, octal, hex), more features than big.js, lighter than decimal.js. For financial calculations: big.js (simple, fast, focused). For scientific computing with trig/log: decimal.js. For general-purpose arbitrary precision with base conversion: bignumber.js.

Key Takeaways

  • decimal.js: ~10M weekly downloads — most features, trig/log, Decimal128-compatible
  • big.js: ~35M weekly downloads — smallest (6KB), focused on decimal arithmetic
  • bignumber.js: ~25M weekly downloads — middle ground, arbitrary base support
  • All three solve the 0.1 + 0.2 !== 0.3 floating point problem
  • For money: reach for dinero.js or integer arithmetic first — arbitrary precision is usually overkill
  • All three are from the same author (MikeMcl) — similar APIs, different feature sets

Why Arbitrary Precision?

// JavaScript floating point failures:
0.1 + 0.2              // 0.30000000000000004
(0.1 + 0.2) === 0.3    // false
1.005.toFixed(2)        // "1.00" (not "1.01")
9007199254740992 + 1    // 9007199254740992 (MAX_SAFE_INTEGER overflow)
Math.sqrt(2)            // 1.4142135623730951 (limited precision)

// When you need exact arithmetic:
// - Financial calculations beyond cents
// - Scientific computing requiring many significant digits
// - Cryptography (large integer arithmetic)
// - Arbitrary-precision constants (π, e, etc.)
// - Tax calculations with complex rounding rules

big.js

big.js — small, focused decimal arithmetic:

Basic usage

import Big from "big.js"

// Create:
const price = new Big("19.99")    // Always pass strings for exact values
const tax = new Big("0.08")

// Arithmetic:
const taxAmount = price.times(tax)
console.log(taxAmount.toFixed(2))  // "1.60" (not 1.5992000000000002)
console.log(price.plus(taxAmount).toFixed(2))  // "21.59"

// Chaining:
const total = new Big("19.99")
  .times("1.08")           // 8% tax included
  .round(2)                // Round to 2 decimal places
  .toFixed(2)              // "21.59"

// Comparisons:
const a = new Big("10.1")
const b = new Big("10.10")

a.eq(b)    // true (equal)
a.gt(b)    // false (not greater than)
a.lt(b)    // false (not less than)
a.gte(b)   // true (greater than or equal)

Configuring precision and rounding

import Big from "big.js"

// Global settings (affects all Big instances):
Big.DP = 20     // Decimal places for division (default: 20)
Big.RM = 1      // Rounding mode (0=down, 1=half-up, 2=half-even, 3=up)

// Per-calculation control:
const result = new Big("10").div("3").toFixed(5)
// "3.33333"

// Round to specific places:
new Big("1.555").round(2)           // Big("1.56") — half-up
new Big("1.555").round(2, 0)        // Big("1.55") — round down
new Big("1.555").round(2, 2)        // Big("1.56") — half-even (banker's)

// Convert to number (use only when exact precision no longer needed):
const price = new Big("19.99")
Number(price)       // 19.99
price.toNumber()    // 19.99

// Format:
new Big("1234567.89").toFixed(2)    // "1234567.89"
new Big("0.000001").toExponential(2) // "1.00e-6"

Financial use case

import Big from "big.js"

interface LineItem {
  description: string
  unitPrice: string  // Store as string to avoid floating point
  quantity: number
}

function calculateInvoice(items: LineItem[], taxRate: string) {
  const subtotal = items.reduce(
    (sum, item) => sum.plus(new Big(item.unitPrice).times(item.quantity)),
    new Big("0")
  )

  const tax = subtotal.times(new Big(taxRate)).round(2, Big.roundHalfUp)
  const total = subtotal.plus(tax)

  return {
    subtotal: subtotal.toFixed(2),
    tax: tax.toFixed(2),
    total: total.toFixed(2),
  }
}

const invoice = calculateInvoice(
  [
    { description: "Plan A", unitPrice: "99.99", quantity: 12 },
    { description: "Add-on", unitPrice: "19.99", quantity: 3 },
  ],
  "0.09"  // 9% tax
)
// { subtotal: "1259.85", tax: "113.39", total: "1373.24" }

decimal.js

decimal.js — full-featured arbitrary precision:

Basic usage

import Decimal from "decimal.js"

// Create:
const x = new Decimal("1.23456789012345678901234567890")

// Same arithmetic operations as big.js, plus:
// Trigonometric functions:
Decimal.sin(new Decimal("1.5707963267948966"))   // sin(π/2) ≈ 1
Decimal.cos(new Decimal("0"))                    // cos(0) = 1
Decimal.tan(new Decimal("0.7853981633974484"))   // tan(π/4) ≈ 1

// Logarithms:
Decimal.ln(new Decimal("2.718281828459045"))     // ln(e) ≈ 1
Decimal.log10(new Decimal("100"))                // 2
Decimal.log2(new Decimal("8"))                   // 3

// Power and square root:
new Decimal("2").pow(new Decimal("0.5"))         // √2 = 1.4142135623...
Decimal.sqrt(new Decimal("2"))                   // Same result
new Decimal("e").exp()                           // e^e

High precision constants

import Decimal from "decimal.js"

// Set precision to 50 significant digits:
Decimal.set({ precision: 50 })

// Compute π to 50 digits:
Decimal.acos(-1).toString()
// "3.1415926535897932384626433832795028841971693993751"

// Euler's number e to 50 digits:
Decimal.exp(1).toString()
// "2.7182818284590452353602874713526624977572470936999"

// Golden ratio:
new Decimal(1).plus(Decimal.sqrt(5)).div(2).toString()
// "1.6180339887498948482045868343656381177203091798058"

Configuration

import Decimal from "decimal.js"

// Configure globally:
Decimal.set({
  precision: 20,          // Significant digits (default: 20)
  rounding: 4,            // Half-up (default: 4)
  // Rounding modes:
  // 0 = round down (truncate)
  // 1 = round towards zero
  // 2 = round towards +Infinity
  // 3 = round towards -Infinity
  // 4 = half up (round half away from zero)
  // 5 = half even (banker's rounding)
  // 6 = half down
  // 7 = half towards zero
  // 8 = Euclid's rule

  toExpNeg: -7,           // Use exponential notation below this exponent
  toExpPos: 21,           // Use exponential notation above this exponent
})

// Or create a scoped Decimal constructor:
const D = Decimal.clone({ precision: 50, rounding: 5 })
const pi = D.acos(-1)  // π to 50 digits with banker's rounding

bignumber.js

bignumber.js — general-purpose, multi-base:

Basic usage

import BigNumber from "bignumber.js"

// Like big.js and decimal.js but with arbitrary base support:
const x = new BigNumber("1234567890.123456789")

// Standard arithmetic:
x.plus("0.000000001").toFixed()  // "1234567890.123456790"
x.times("2").toFixed()           // "2469135780.246913578"

// More formatting options:
x.toFormat(2)          // "1,234,567,890.12" (with grouping)
x.toFormat(2, { groupSeparator: ".", decimalSeparator: "," })
// "1.234.567.890,12" (European format)

Multi-base conversion

import BigNumber from "bignumber.js"

// Arbitrary base support (2-36):
const decimal = new BigNumber(255)

decimal.toString(16)    // "ff" (hex)
decimal.toString(2)     // "11111111" (binary)
decimal.toString(8)     // "377" (octal)

// Convert from arbitrary base:
new BigNumber("ff", 16).toNumber()    // 255
new BigNumber("11111111", 2).toNumber()  // 255

// Hex with padding:
new BigNumber("FF8800", 16).toString()  // "16744448"

// Useful for: cryptographic big integers, color codes, encoding systems

Comparison with big.js

// big.js vs bignumber.js vs decimal.js
// (all from same author, MikeMcl)

// big.js:
// + Smallest (6KB)
// + Simple API
// - No trig/log, no base conversion, limited rounding modes
// Use for: financial calculations, simple decimal math

// bignumber.js:
// + More features than big.js (base conversion, more rounding modes)
// + Better formatting options (toFormat with locales)
// - Bigger than big.js (~20KB)
// Use for: general-purpose, need base conversion or better formatting

// decimal.js:
// + Most features (trig, log, exp, all rounding modes)
// + Decimal128 compatible for database storage
// - Largest (~30KB)
// Use for: scientific computing, complex math, Decimal128 databases

Feature Comparison

Featurebig.jsbignumber.jsdecimal.js
Bundle size~6KB~20KB~30KB
Decimal precision
Trig/log functions
Arbitrary base✅ (2-36)
Formatting (toFormat)
Rounding modes499
Decimal128 compat
TypeScript
ESM
Browser

When to Use Each

Choose big.js if:

  • Financial calculations requiring exact decimal arithmetic
  • You want the smallest possible bundle for browser use
  • Simple add/subtract/multiply/divide with configurable rounding
  • API simplicity over feature richness

Choose bignumber.js if:

  • You need base conversion (binary/hex/octal ↔ decimal)
  • Better locale-aware number formatting with toFormat()
  • More rounding modes than big.js provides
  • General-purpose arbitrary precision without trig

Choose decimal.js if:

  • Scientific computing requiring trigonometric or logarithmic functions
  • You need a Decimal128-compatible value for MongoDB or PostgreSQL
  • Complex mathematical operations beyond basic arithmetic
  • Maximum precision (up to ~1e9 significant digits)

Stick with native numbers if:

// For most web apps, native numbers are fine:
const price = 19.99
const tax = Math.round(price * 0.08 * 100) / 100  // = 1.60 (rounded to cents)
const total = Math.round((price + tax) * 100) / 100  // = 21.59

// Integer cents approach covers 99% of financial use cases:
const priceInCents = 1999
const taxInCents = Math.round(priceInCents * 0.08)   // 160
const totalInCents = priceInCents + taxInCents         // 2159

// Use arbitrary precision only when:
// 1. Precision beyond 15 significant digits is required
// 2. Many chained operations that compound floating point errors
// 3. Scientific/crypto applications needing exact arbitrary precision

Methodology

Download data from npm registry (weekly average, February 2026). Feature comparison based on big.js v6.x, bignumber.js v9.x, and decimal.js v10.x. All three libraries are maintained by the same author (MikeMcl).

Compare math and utility packages on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.