Skip to main content

Number Methods

Numbers in JavaScript

JavaScript uses a single number type for both integers and floating-point values, based on the IEEE 754 double-precision format. This causes some famous quirks — but also a rich set of methods to work around them.

typeof 42; // "number"
typeof 3.14; // "number"
typeof NaN; // "number" — NaN is technically of type number
typeof Infinity; // "number"

Parsing Strings to Numbers

Number()

Converts a whole string to a number. Fails fast — returns NaN if any part is non-numeric:

Number("42"); // 42
Number("3.14"); // 3.14
Number(""); // 0
Number(" 42 "); // 42 (trims whitespace)
Number("42px"); // NaN
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN

parseInt(string, radix)

Parses from the start, stops at the first non-numeric character. Always pass the radix:

parseInt("42px", 10); // 42 — stops at 'p'
parseInt("3.9", 10); // 3 — truncates decimal
parseInt("0xff", 16); // 255 — hex
parseInt("101", 2); // 5 — binary
parseInt("hello", 10); // NaN — starts with non-numeric
Always pass the radix

Without the second argument, parseInt("08") was historically interpreted as octal in some engines, returning 0. Always write parseInt(str, 10) for decimal parsing.

parseFloat()

Parses decimal numbers from a string:

parseFloat("3.14abc"); // 3.14
parseFloat("3.14"); // 3.14
parseFloat("42"); // 42
parseFloat("abc"); // NaN

Checking Numbers

Number.isNaN() vs global isNaN()

Number.isNaN(NaN); // true
Number.isNaN("hello"); // false — does NOT coerce
Number.isNaN(undefined); // false

isNaN("hello"); // true — coerces to NaN first (misleading!)
isNaN(undefined); // true — coerces to NaN (misleading!)

Always use Number.isNaN() — the global isNaN() has unintuitive coercion behavior.

Number.isFinite() vs global isFinite()

Number.isFinite(42); // true
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite(NaN); // false
Number.isFinite("42"); // false — no coercion

isFinite("42"); // true — coerces "42" to 42 first

Again, prefer Number.isFinite().

Number.isInteger()

Number.isInteger(42); // true
Number.isInteger(42.0); // true — .0 is an integer
Number.isInteger(42.5); // false
Number.isInteger("42"); // false — no coercion

Number.isSafeInteger()

JavaScript can only safely represent integers up to 2^53 - 1:

Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MIN_SAFE_INTEGER; // -9007199254740991

Number.isSafeInteger(9007199254740991); // true
Number.isSafeInteger(9007199254740992); // false — precision lost

For larger integers, use BigInt:

const big = 9007199254740993n; // BigInt literal (n suffix)

Formatting Numbers

toFixed(decimals)

Returns a string with a fixed number of decimal places:

(3.14159).toFixed(2); // "3.14"
(3.1).toFixed(4); // "3.1000"
(3.7).toFixed(0); // "4" — rounds

// Common use: currency display
const price = 9.999;
`$${price.toFixed(2)}`; // "$10.00"
note
toFixed returns a string

(1.5).toFixed(2) returns "1.50", not 1.50. Wrap with Number() if you need arithmetic on it.

toPrecision(digits)

Specifies total significant digits:

(123.456).toPrecision(5); // "123.46"
(0.000123).toPrecision(2); // "0.00012"

toString(radix)

Convert a number to a different base:

(255).toString(16); // "ff" — hex
(255).toString(2); // "11111111" — binary
(255).toString(8); // "377" — octal
(42).toString(); // "42" — decimal (default)

Intl.NumberFormat — Locale-Aware Formatting

For displaying numbers to users, use the Intl.NumberFormat API:

// Currency
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
.format(1234567.89);
// "$1,234,567.89"

new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" })
.format(1234567.89);
// "1.234.567,89 €"

// Compact notation
new Intl.NumberFormat("en", { notation: "compact" }).format(1_500_000);
// "1.5M"

// Percentage
new Intl.NumberFormat("en", { style: "percent" }).format(0.75);
// "75%"

Math Object

Common static methods on the global Math object:

Math.round(4.5); // 5 — rounds to nearest
Math.floor(4.9); // 4 — always rounds down
Math.ceil(4.1); // 5 — always rounds up
Math.trunc(4.9); // 4 — removes decimal (no rounding)
Math.trunc(-4.9); // -4 — note: different from floor for negatives

Math.abs(-5); // 5
Math.min(1, 2, 3); // 1
Math.max(1, 2, 3); // 3
Math.pow(2, 8); // 256
Math.sqrt(16); // 4
Math.cbrt(27); // 3 (cube root)
Math.log2(8); // 3
Math.log10(1000); // 3

Math.PI; // 3.141592653589793
Math.E; // 2.718281828459045

Random Numbers

Math.random(); // float between 0 (inclusive) and 1 (exclusive)

// Random integer between min and max (inclusive)
const randomInt = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;

randomInt(1, 6); // simulates a dice roll: 1-6
randomInt(0, 99); // 0-99

The Floating-Point Problem

0.1 + 0.2; // 0.30000000000000004 ← not 0.3!

This is not a JavaScript bug — it's how IEEE 754 floating-point arithmetic works in every language. Solutions:

// For display — round to sensible precision
(0.1 + 0.2).toFixed(2); // "0.30"

// For comparisons — use toBeCloseTo in tests, or epsilon check
Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON; // true

// For currency — work in cents (integers), never floats
const priceInCents = 199; // $1.99
const taxInCents = Math.round(priceInCents * 0.1); // 20 cents
const totalInCents = priceInCents + taxInCents; // 219 cents
const display = `$${(totalInCents / 100).toFixed(2)}`; // "$2.19"

Quick Reference

MethodPurposeReturns
Number(val)Convert to numbernumber
parseInt(str, 10)Parse integer from stringnumber
parseFloat(str)Parse float from stringnumber
Number.isNaN(val)Check if NaN (no coercion)boolean
Number.isFinite(val)Check if finite (no coercion)boolean
Number.isInteger(val)Check if integerboolean
num.toFixed(n)Fixed decimal placesstring
num.toString(base)Convert to base (hex, binary)string
Math.round/floor/ceilRoundingnumber
Math.random()Random 0–1number