JavaScript Math Object

5 minute read

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 ** over Math.pow for readability
  • ✅ Use Math.hypot for distances (more stable than sqrt(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.round for “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.

← Previous: JS Date Objects Next: JS Conditionals →

Updated: