Numbers, Math and BigInt

JavaScript · Essentials · 10 min

Money, IDs and user input all hit the edges of floating point sooner or later.

Every number is a 64-bit IEEE-754 double. There is no separate integer type, so 1 and 1.0 are the same value. Integers are exact up to Number.MAX_SAFE_INTEGER (2^53 − 1); beyond that, adjacent integers can't all be represented.

Decimal fractions are approximations: 0.1 + 0.2 is 0.30000000000000004. For money, compute in integer cents (or use a decimal library) and only format at the end.

Special values: Infinity, -Infinity and NaN ("not a number"), which results from invalid math like 0 / 0 or Number("abc").

Converting text to numbers:

  • Number("42") converts the whole string and returns NaN if anything is left over.
  • parseInt("42px", 10) and parseFloat read a leading number and ignore the rest. Always pass the radix to parseInt.

Useful helpers: Number.isInteger, Number.isFinite, Math.round/floor/ceil/trunc, Math.max/min, Math.random() (0 inclusive to 1 exclusive). n.toFixed(2) rounds for display and returns a string.

For display to humans use Intl.NumberFormat, which handles separators, currencies and locales: new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(1234.5) gives "$1,234.50".

When you need exact integers larger than 2^53 — database IDs, cryptography — use BigInt: write 123n or BigInt("123"). BigInts can't be mixed with numbers in arithmetic (1n + 1 throws), so convert explicitly. Numeric separators (1_000_000) work for both.

Example

console.log(0.1 + 0.2);                  // 0.30000000000000004
console.log((0.1 + 0.2).toFixed(2));     // "0.30" (a string)

console.log(Number("12px"));             // NaN
console.log(parseInt("12px", 10));       // 12
console.log(Number.isNaN(0 / 0));        // true

const priceCents = 1999 * 3;             // compute money in integers
const fmt = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
console.log(fmt.format(priceCents / 100)); // "$59.97"

console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 (wrong!)
console.log(9007199254740991n + 2n);      // 9007199254740993n
const big = 1_000_000n * BigInt(3);       // convert before mixing
console.log(big);                         // 3000000n

Remember

  • All numbers are doubles: fractions are approximate, integers are safe up to 2^53 − 1
  • Number() is strict, parseInt(str, 10) reads a numeric prefix
  • Format for people with Intl.NumberFormat; use BigInt for huge exact integers

Watch out for

  • Treating the result of toFixed as a number — it is a string.

Check yourself

  1. What do Number("12px") and parseInt("12px", 10) return?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number

Builds on

Unlocks

Nothing builds on this yet.