Math Utilities

GCD, LCM, factorial, Fibonacci, statistics (median, mode, standard deviation), prime checking, and other math helpers that developers always have to look up.

clamp

Restrict a number to a range. (Also in Number Utilities — repeated here for discoverability.)

const clamp = (value, min, max) => Math.min(Math.max(value, min), max);

clamp(15, 0, 10);  // 10
clamp(-5, 0, 10);  // 0
clamp(5,  0, 10);  // 5

GCD (Greatest Common Divisor)

const gcd = (a, b) => (b === 0 ? Math.abs(a) : gcd(b, a % b));

gcd(12, 8);   // 4
gcd(100, 75); // 25
gcd(0, 5);    // 5

LCM (Least Common Multiple)

const lcm = (a, b) => Math.abs(a * b) / gcd(a, b);

// For multiple numbers
const lcmMany = (...nums) => nums.reduce(lcm);

lcm(4, 6);          // 12
lcm(12, 18);        // 36
lcmMany(4, 6, 8);   // 24

factorial

const factorial = (n) => {
  if (n < 0) throw new RangeError("Factorial of negative number");
  if (n === 0 || n === 1) return 1;
  return n * factorial(n - 1);
};

factorial(0);  // 1
factorial(5);  // 120
factorial(10); // 3628800

fibonacci

// Iterative (efficient — no stack overflow)
const fibonacci = (n) => {
  if (n < 0) throw new RangeError("Input must be non-negative");
  if (n <= 1) return n;
  let [a, b] = [0, 1];
  for (let i = 2; i <= n; i++) [a, b] = [b, a + b];
  return b;
};

fibonacci(0);  // 0
fibonacci(1);  // 1
fibonacci(10); // 55
fibonacci(50); // 12586269025

// Generate the first N fibonacci numbers
const fibSequence = (n) =>
  Array.from({ length: n }, (_, i) => fibonacci(i));

fibSequence(8); // [0, 1, 1, 2, 3, 5, 8, 13]

isPrime

const isPrime = (n) => {
  if (n < 2) return false;
  if (n === 2) return true;
  if (n % 2 === 0) return false;
  for (let i = 3; i <= Math.sqrt(n); i += 2) {
    if (n % i === 0) return false;
  }
  return true;
};

isPrime(2);   // true
isPrime(17);  // true
isPrime(18);  // false
isPrime(97);  // true

getPrimes (Sieve of Eratosthenes)

Get all prime numbers up to N.

const getPrimes = (limit) => {
  const sieve = new Array(limit + 1).fill(true);
  sieve[0] = sieve[1] = false;
  for (let i = 2; i * i <= limit; i++) {
    if (sieve[i]) {
      for (let j = i * i; j <= limit; j += i) sieve[j] = false;
    }
  }
  return sieve.reduce((primes, isPrime, i) => (isPrime ? [...primes, i] : primes), []);
};

getPrimes(20); // [2, 3, 5, 7, 11, 13, 17, 19]
getPrimes(50).length; // 15 primes below 50

median

const median = (arr) => {
  if (arr.length === 0) return undefined;
  const sorted = [...arr].sort((a, b) => a - b);
  const mid = Math.floor(sorted.length / 2);
  return sorted.length % 2 !== 0
    ? sorted[mid]
    : (sorted[mid - 1] + sorted[mid]) / 2;
};

median([1, 3, 5]);        // 3
median([1, 2, 3, 4]);     // 2.5
median([7, 1, 5, 3, 9]); // 5

mode

Return the most frequently occurring value(s).

const mode = (arr) => {
  const freq = arr.reduce((acc, v) => { acc[v] = (acc[v] ?? 0) + 1; return acc; }, {});
  const max = Math.max(...Object.values(freq));
  return Object.keys(freq)
    .filter((k) => freq[k] === max)
    .map(Number);
};

mode([1, 2, 2, 3]);        // [2]
mode([1, 1, 2, 2, 3]);    // [1, 2]  (tie)
mode([5, 5, 5, 1, 2]);    // [5]

mean (average)

const mean = (arr) => arr.reduce((sum, n) => sum + n, 0) / arr.length;

mean([1, 2, 3, 4, 5]); // 3
mean([10, 20, 30]);    // 20

standardDeviation

const standardDeviation = (arr, population = false) => {
  const avg = mean(arr);
  const squaredDiffs = arr.map((n) => (n - avg) ** 2);
  const variance = mean(squaredDiffs) * (population ? 1 : arr.length / (arr.length - 1));
  return Math.sqrt(variance);
};

standardDeviation([2, 4, 4, 4, 5, 5, 7, 9]);           // 2 (population)
standardDeviation([2, 4, 4, 4, 5, 5, 7, 9], false);   // sample std dev

isPowerOfTwo

const isPowerOfTwo = (n) => n > 0 && (n & (n - 1)) === 0;

isPowerOfTwo(1);   // true
isPowerOfTwo(8);   // true
isPowerOfTwo(16);  // true
isPowerOfTwo(10);  // false

lerp / inverseLerp / remap

// Linear interpolation
const lerp = (a, b, t) => a + (b - a) * t;

// Inverse: find t given a value between a and b
const inverseLerp = (a, b, value) => (value - a) / (b - a);

// Remap a value from one range to another
const remap = (value, fromA, fromB, toA, toB) =>
  lerp(toA, toB, inverseLerp(fromA, fromB, value));

lerp(0, 100, 0.25);          // 25
inverseLerp(0, 100, 25);     // 0.25
remap(50, 0, 100, 0, 1);     // 0.5
remap(0, -1, 1, 0, 360);     // 180  (map -1..1 → 0..360 degrees)

Summary

FunctionInputOutput
gcd(12, 8)12, 84
lcm(4, 6)4, 612
factorial(5)5120
fibonacci(10)1055
isPrime(17)17true
getPrimes(20)20[2,3,5,7,11,13,17,19]
median([1,2,3,4])array2.5
mode([1,1,2,2,3])array[1,2]
standardDeviation(arr)arraystd dev
isPowerOfTwo(8)8true
lerp(0, 100, 0.25)0, 100, 0.2525
remap(50, 0, 100, 0, 1)0.5