Numbers
JavaScript famously has one number type. Whether you write 42, 3.14, -7 or 1e9, the engine stores them all the same way — as 64-bit double-precision floating-point values, the format defined by the IEEE 754 standard. That single decision shapes most of the quirks you'll meet on this page: limited precision, weird edge cases like NaN and Infinity, and the existence of a separate BigInt type for when 64 bits aren't enough.
One type to rule them all
There is no int, float, double or long in JavaScript. The typeof of every number — integer or not — is just "number".
console.log(typeof 42); // "number" console.log(typeof 3.14); // "number" console.log(typeof -0); // "number" console.log(typeof NaN); // "number" console.log(typeof Infinity); // "number"
number number number number number
How numbers are stored (IEEE 754)
A 64-bit double splits into one sign bit, eleven exponent bits and fifty-two fraction bits. The practical implications:
Integers are exact up to 2^53 − 1 (
Number.MAX_SAFE_INTEGER, 9,007,199,254,740,991). Beyond that, integers start skipping values.Fractional numbers in base 10 often have no exact binary representation — the same way 1/3 has no exact decimal representation.
The largest representable value is
Number.MAX_VALUE(~1.79e308). Anything bigger becomesInfinity.The smallest positive value is
Number.MIN_VALUE(~5e-324). Smaller magnitudes underflow to0.
Number literals
You can write the same value in several ways depending on the base or the readability you want:
const dec = 255; // decimal const hex = 0xff; // hexadecimal — also 255 const bin = 0b1111_1111; // binary — also 255 const oct = 0o377; // octal — also 255 const big = 1_000_000; // numeric separators are just visual const sci = 6.022e23; // scientific notation const tiny = 1.6e-19; // small numbers too console.log(dec === hex && hex === bin && bin === oct); // true console.log(big); // 1000000 console.log(sci); // 6.022e+23
The 0.1 + 0.2 problem
The most-quoted JavaScript gotcha is not a JavaScript bug — it is a property of binary floating-point shared by Python, Java, C and almost every other mainstream language.
console.log(0.1 + 0.2); // 0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // false
The numbers 0.1 and 0.2 cannot be stored exactly in binary; the tiny rounding errors accumulate when they're added. Two common ways to deal with it:
// 1. Compare with a small tolerance (epsilon) const a = 0.1 + 0.2; console.log(Math.abs(a - 0.3) < Number.EPSILON); // true // 2. Work in the smallest unit (e.g. cents, not dollars) const totalCents = 10 + 20; // 30 const totalDollars = totalCents / 100; // 0.3
Special values: NaN, Infinity, -0
A few numbers behave unlike "ordinary" numbers and trip up beginners constantly.
// Infinity — from overflow or explicit division by zero
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(1e308 * 10); // Infinity
// NaN — "not a number". The result of an impossible numeric operation.
console.log(0 / 0); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(Number("abc")); // NaN
// NaN is the only value not equal to itself
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // true — use this to test
// Signed zero — yes, JavaScript has -0
console.log(0 === -0); // true
console.log(Object.is(0, -0)); // false — Object.is can tell them apart
console.log(1 / -0); // -InfinityUseful constants on the Number object
Number.MAX_SAFE_INTEGER; // 9007199254740991 Number.MIN_SAFE_INTEGER; // -9007199254740991 Number.MAX_VALUE; // ~1.79e308 Number.MIN_VALUE; // ~5e-324 (smallest positive, not most negative) Number.POSITIVE_INFINITY; // Infinity Number.NEGATIVE_INFINITY; // -Infinity Number.EPSILON; // ~2.22e-16 — smallest meaningful difference near 1 Number.NaN; // NaN
A number is "safe" if it can be represented exactly as a double and is not the result of rounding any other integer. Beyond MAX_SAFE_INTEGER, you can no longer trust integer arithmetic.
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992 console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 (!)
9007199254740991 9007199254740992 9007199254740992
If you need exact integers beyond that range — large IDs from a database, cryptocurrency amounts, big factorials — use BigInt (covered on its own page).
Quick reference: precision gotchas
0.1 + 0.2 !== 0.3— use a tolerance or work in integers.Math.max() === -InfinityandMath.min() === Infinity— the "identity" elements when no arguments are passed.parseInt("0.1")is0, not0.1—parseIntstops at the dot.+ "12px"isNaN— coercion is strict,parseInt("12px")gives12.1 / 0isInfinity, not an error. Check withNumber.isFinitebefore dividing.
Numbers feel simple — and for everyday counts and prices they are — but the IEEE 754 model leaks through in small, predictable ways. The rest of this section covers the methods you'll use to round, parse, format and inspect numeric values safely.