JavaScript Number Tricks Every Developer Should Know
Numbers in JS are weird. Here's how to handle them correctly.
The Floating Point Problem
0.1 + 0.2 === 0.3 // false! → 0.30000000000000004
// Why? IEEE 754 double precision can't represent 0.1 exactly
// Fix: Use integer math
const price = (0.1 * 100 + 0.2 * 100) / 100; // 0.3 ✅
// Or use toFixed for display
(0.1 + 0.2).toFixed(2); // "0.30"
// Or use a library for money: currency.js, dinero.js, decimal.js
Useful Number Methods
// Rounding
Math.round(4.5); // 5 (rounds to nearest, 0.5 rounds up)
Math.round(4.4); // 4
Math.floor(4.9); // 4 (always down)
Math.ceil(4.1); // 5 (always up)
Math.trunc(4.9); // 4 (remove decimal, no rounding)
// Decimal precision
(1.005).toFixed(2); // "1.00" ❌ (wrong!)
(1.005 * 100 + Number.EPSILON).toFixed(2) / 100; // 1.01 ✅
// Random numbers
Math.random(); // 0 to < 1
Math.floor(Math.random() * 10); // 0 to 9
Math.floor(Math.random() * 10) + 1; // 1 to 10
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
randInt(1, 100); // Random integer 1-100
// Random from array
const colors = ['red', 'green', 'blue'];
colors[Math.floor(Math.random() * colors.length)];
// Shuffle array (Fisher-Yates)
function shuffle(arr) {
const a = [...arr];
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
Number Formatting
// Currency
const price = 1234567.89;
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(price);
// "$1,234,567.89"
new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(price);
// "¥1,234,568" (no decimals for JPY)
// Thousands separator
new Intl.NumberFormat().format(1234567); // "1,234,567"
// Compact notation
new Intl.NumberFormat('en', { notation: 'compact' }).format(1500000);
// "1.5M"
// Percentage
new Intl.NumberFormat('en', { style: 'percent' }).format(0.85);
// "85%"
// Fixed decimals
(42).toFixed(2); // "42.00"
(42.678).toFixed(2); // "42.68"
// Significant digits
(123456).toPrecision(3); // "1.23e+5"
(123.456).toPrecision(4); // "123.5"
// Bytes to human-readable
function formatBytes(bytes) {
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let i = 0;
let size = bytes;
while (size >= 1024 && i < units.length - 1) {
size /= 1024;
i++;
}
return `${size.toFixed(1)} ${units[i]}`;
}
formatBytes(1536); // "1.5 KB"
formatBytes(1073741824); // "1.0 GB"
Math Shortcuts
// Clamp a value between min and max
const clamp = (val, min, max) => Math.min(Math.max(val, min), max);
clamp(150, 0, 100); // 100
clamp(-50, 0, 100); // 0
clamp(50, 0, 100); // 50
// Distance between two points
const distance = (x1, y1, x2, y2) =>
Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
// Linear interpolation
const lerp = (start, end, t) => start + (end - start) * t;
lerp(0, 100, 0.5); // 50
lerp(0, 100, 0.75); // 75
// Map value from one range to another
const map = (val, inMin, inMax, outMin, outMax) =>
outMin + (outMax - outMin) * ((val - inMin) / (inMax - inMin));
map(5, 0, 10, 0, 100); // 50
map(3, 0, 10, -1, 1); // -0.4
// Average
const avg = (...nums) => nums.reduce((a, b) => a + b, 0) / nums.length;
avg(1, 2, 3, 4, 5); // 3
// Sum
const sum = (...nums) => nums.reduce((a, b) => a + b, 0);
sum(1, 2, 3, 4, 5); // 15
// Min/Max from array
const numbers = [3, 7, 2, 9, 1, 5];
Math.min(...numbers); // 1
Math.max(...numbers); // 9
// GCD (Greatest Common Divisor)
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
gcd(12, 8); // 4
// Prime check
const isPrime = (n) => {
if (n < 2) return false;
for (let i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) return false;
}
return true;
};
Bitwise Tricks
// Check if number is even/odd
5 & 1; // 1 (odd)
4 & 1; // 0 (even)
// Faster than n % 2 (marginally)
// Swap without temp variable
let a = 10, b = 20;
a ^= b; b ^= a; a ^= b;
// a = 20, b = 10
// Power of 2 check
const isPowerOf2 = (n) => n > 0 && (n & (n - 1)) === 0;
isPowerOf2(8); // true
isPowerOf2(10); // false
// Fast multiply/divide by 2
n << 1; // n * 2
n >> 1; // n / 2 (integer division)
parseInt Gotchas
parseInt('123'); // 123
parseInt('123abc'); // 123 (stops at non-digit)
parseInt('abc123'); // NaN
parseInt('0xFF'); // 255 (hex)
parseInt('0o77'); // 63 (octal)
parseInt('0b1010'); // 0 (binary NOT supported without radix!)
// ⚠️ ALWAYS specify radix
parseInt('10', 10); // 10 (decimal)
parseInt('10', 2); // 2 (binary)
parseInt('10', 8); // 8 (octal)
parseInt('10', 16); // 16 (hex)
parseInt('10', 36); // 36 (base 36)
// Number() vs parseInt()
Number('123abc'); // NaN (strict)
parseInt('123abc'); // 123 (lenient)
Number(''); // 0
parseInt(''); // NaN
Number(true); // 1
parseInt(true); // NaN
Type Checking
Number.isFinite(42); // true
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Number.isInteger(42); // true
Number.isInteger(42.0); // true
Number.isInteger(42.5); // false
Number.isNaN(NaN); // true
Number.isNaN('hello'); // false (global isNaN would return true!)
Number.isSafeInteger(9007199254740991); // true (max safe integer)
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false
What's your favorite number trick in JavaScript?
Follow @armorbreak for more JS content.
Top comments (0)