JavaScript Math Object
Math is JavaScript’s built-in numeric helper namespace — pure functions and a handful of constants for rounding, trig, exponents, and randomness. It’s not a class; you never instantiate it. You just call Math.something(x). This chapter walks through the methods you’ll actually reach for, the ones beginners get wrong, and a few patterns worth memorising.
Constants
| Constant | Value | What |
|---|---|---|
Math.PI |
3.14159… | π |
Math.E |
2.71828… | Euler’s number |
Math.LN2 |
0.693… | ln(2) |
Math.LN10 |
2.302… | ln(10) |
Math.LOG2E |
1.442… | log₂(e) |
Math.LOG10E |
0.434… | log₁₀(e) |
Math.SQRT2 |
1.414… | √2 |
Math.PI; // 3.141592653589793
2 * Math.PI; // circumference / radius
Rounding — The Big Four
| Method | Behaviour | Example: 2.5 |
Example: -2.5 |
|---|---|---|---|
Math.round |
half rounds toward +∞ | 3 |
-2 |
Math.floor |
toward -∞ | 2 |
-3 |
Math.ceil |
toward +∞ | 3 |
-2 |
Math.trunc |
toward zero (chop) | 2 |
-2 |
Math.round( 2.5); // 3
Math.round(-2.5); // -2 ← surprising! not symmetric
Math.floor(2.9); // 2
Math.ceil( 2.1); // 3
Math.trunc(-2.9); // -2 ← drops decimals, no rounding
// Quick "integer part" — bitwise NOT NOT, faster than Math.trunc, ≤ 32-bit only
~~3.7; // 3
~~-3.7; // -3
Warning: Math.round(-2.5) returns -2, not -3. Half-values round toward positive infinity. If you want “round half away from zero”, roll your own.
Round to N Decimals
function round(n, places = 0) {
const factor = 10 ** places;
return Math.round(n * factor) / factor;
}
round(1.2345, 2); // 1.23
round(1.005, 2); // 1 ← float-precision quirk!
// More robust, via toFixed
function roundFixed(n, places) {
return Number(n.toFixed(places));
}
roundFixed(1.005, 2); // 1.01
Min / Max
Math.min(3, 1, 2); // 1
Math.max(3, 1, 2); // 3
Math.min(); // Infinity ← no args
Math.max(); // -Infinity
const arr = [3, 1, 4, 1, 5, 9];
Math.min(...arr); // 1
Math.max(...arr); // 9
// For huge arrays (length over the call-stack limit ~100k), use a reducer
arr.reduce((m, x) => x < m ? x : m, Infinity);
Absolute Value, Sign, Hypotenuse
Math.abs(-7); // 7
Math.abs(-0); // 0
Math.sign(-5); // -1
Math.sign(0); // 0
Math.sign(5); // 1
Math.sign(NaN); // NaN
Math.hypot(3, 4); // 5 sqrt(3² + 4²)
Math.hypot(1, 2, 2); // 3 sqrt(1+4+4)
hypot is more numerically stable than Math.sqrt(a*a + b*b) for very large or very small numbers.
Powers and Roots
Math.pow(2, 10); // 1024 (use 2 ** 10 instead)
Math.sqrt(81); // 9
Math.cbrt(27); // 3
Math.exp(1); // 2.718… (e¹)
Math.expm1(1); // e¹ - 1 (more accurate near 0)
The ** operator is preferred over Math.pow since ES2016:
2 ** 10; // 1024
9 ** 0.5; // 3
2n ** 64n; // BigInt power
Logarithms
Math.log(Math.E); // 1 natural log
Math.log2(1024); // 10
Math.log10(1000); // 3
Math.log1p(0); // 0 log(1 + x) — accurate near 0
// log_b(x) = log(x) / log(b)
const logBase = (b, x) => Math.log(x) / Math.log(b);
logBase(3, 81); // 4
Trigonometry
All trig functions take radians, not degrees.
Math.sin(Math.PI / 2); // 1
Math.cos(0); // 1
Math.tan(Math.PI / 4); // ~1
Math.asin(1); // π/2
Math.atan2(1, 1); // π/4 — handles all four quadrants
Math.sinh(0); // 0 (hyperbolic)
Math.cosh(0); // 1
Math.tanh(0); // 0
const toRad = deg => deg * Math.PI / 180;
const toDeg = rad => rad * 180 / Math.PI;
Math.sin(toRad(30)); // 0.5
| Use | When |
|---|---|
atan(y/x) |
rarely — loses sign info |
atan2(y, x) |
✅ proper four-quadrant angle |
Random Numbers
Math.random() returns a float in [0, 1):
Math.random(); // e.g. 0.7261…
Math.random() * 100; // 0 ≤ x < 100
Math.floor(Math.random() * 6) + 1; // 1..6 (dice)
Reusable helpers:
const randInt = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
const randFloat = (min, max) =>
Math.random() * (max - min) + min;
const randPick = arr => arr[randInt(0, arr.length - 1)];
randInt(1, 10); // 1..10 inclusive
randPick(["a", "b", "c"]);
Warning: Math.random() is not cryptographically secure — predictable across calls in some engines. For tokens, IDs, passwords, or anything security-sensitive, use crypto.randomUUID() or crypto.getRandomValues().
// Cryptographically secure UUID
crypto.randomUUID();
// "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
// Secure random integer (bytes)
const buf = new Uint32Array(1);
crypto.getRandomValues(buf);
const secureInt = buf[0];
Number Theory Helpers
Math.fround(1.337); // round to nearest 32-bit float
Math.clz32(1); // count leading zeros (32-bit)
Math.imul(2, 3); // 32-bit integer multiplication
These are niche — used in low-level libraries (decoders, compression, graphics). You’ll rarely need them in app code.
Patterns Worth Memorising
// Clamp x into [lo, hi]
const clamp = (x, lo, hi) => Math.min(Math.max(x, lo), hi);
clamp(105, 0, 100); // 100
// Linear interpolation: a→b at t in [0, 1]
const lerp = (a, b, t) => a + (b - a) * t;
lerp(0, 100, 0.25); // 25
// Map x from [inMin, inMax] onto [outMin, outMax]
const mapRange = (x, inMin, inMax, outMin, outMax) =>
outMin + (x - inMin) / (inMax - inMin) * (outMax - outMin);
mapRange(50, 0, 100, 0, 1); // 0.5
// Distance between two 2D points
const distance = (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1);
// Approximate equality (avoid float === pitfalls)
const closeEnough = (a, b, eps = 1e-9) => Math.abs(a - b) < eps;
closeEnough(0.1 + 0.2, 0.3); // true
A Realistic Example — Random Color Generator
function randomHexColor() {
// Generate a random integer in [0, 0xFFFFFF], pad to 6 hex digits
const n = Math.floor(Math.random() * 0x1_000_000);
return "#" + n.toString(16).padStart(6, "0");
}
randomHexColor(); // e.g. "#3a9f0c"
// Random color with controlled brightness
function randomBrightColor() {
const h = Math.floor(Math.random() * 360);
const s = 70 + Math.random() * 20; // 70..90
const l = 45 + Math.random() * 10; // 45..55
return `hsl(${h}, ${s}%, ${l}%)`;
}
randomBrightColor(); // e.g. "hsl(214, 82%, 51%)"
Math.random + Math.floor + padStart (string method) — three primitives composed into a readable utility.
Common Mistakes
// ❌ Math.random() returns 0..1, never reaches 1
Math.floor(Math.random() * 6); // 0..5, NOT 1..6
Math.floor(Math.random() * 6) + 1; // ✅ 1..6
// ❌ Trig in degrees
Math.sin(30); // sin(30 radians) ≈ -0.988
// ✅
Math.sin(30 * Math.PI / 180); // 0.5
// ❌ Math.pow vs **
Math.pow(2, 53); // works but verbose
2 ** 53; // ✅ preferred
// ❌ Using Math.random for IDs
const id = Math.random().toString(36).slice(2); // not unique enough
// ✅
const id = crypto.randomUUID();
Best Practices Checklist
- ✅ Use
**overMath.powfor readability - ✅ Use
Math.hypotfor distances (more stable thansqrt(x*x + y*y)) - ✅ Convert degrees to radians before trig calls
- ✅ Use
crypto.randomUUID()/crypto.getRandomValues()for any security-sensitive randomness - ✅ Cache frequently-used trig results outside hot loops
- ❌ Don’t rely on
Math.roundfor “round half away from zero” — it doesn’t - ❌ Don’t compare floats with
===— use an epsilon - ❌ Don’t pass
Math.random()directly where you need uniqueness
What’s Next?
Numbers fully tooled. Now we shift gears to control flow — branching with if, ternary, and the truthiness rules that surprise everyone at least once.