JavaScript Number Tricks Every Developer Should Know
These aren't math puzzles. These are practical tricks I use in real code.
1. Safe Integer Parsing
// ❌ Common mistakes
parseInt('123abc') // 123 (ignores trailing chars)
parseInt('abc') // NaN (no error message)
parseInt('12.5') // 12 (truncates decimal!)
parseInt('0xFF') // 255 (parses hex!)
// ✅ Use Number() or unary plus
Number('123') // 123
Number('123abc') // NaN
Number('12.5') // 12.5
+'123' // 123 (unary plus)
// ✅ Always validate with Number.isFinite()
function safeParseInt(str, fallback = 0) {
const num = Number(str);
return Number.isFinite(num) ? Math.floor(num) : fallback;
}
safeParseInt('42') // 42
safeParseInt('abc') // 0 (fallback)
safeParseInt('12.9') // 12
safeParseInt('') // 0 (fallback)
2. Floating Point Workarounds
// ❌ Floating point gotchas
0.1 + 0.2 // 0.30000000000000004 (!)
0.1 + 0.2 === 0.3 // false (!!)
9007199254740992 === 9007199254740993 // true (!!!)
// ✅ For money: use integers (cents)
const price = 1299; // $12.99 in cents
const total = price * 3; // 3897 cents = $38.97
console.log('$' + (total / 100).toFixed(2)); // "$38.97"
// ✅ For comparisons: use epsilon
function approxEqual(a, b, epsilon = 1e-10) {
return Math.abs(a - b) < epsilon;
}
approxEqual(0.1 + 0.2, 0.3) // true
approxEqual(0.1 + 0.2, 0.3, 0) // false
// ✅ For formatting: toFixed()
(0.1 + 0.2).toFixed(2) // "0.30"
parseFloat((0.1 + 0.2).toFixed(2)) // 0.3
3. Random Number Utilities
// Random integer in range [min, max] (inclusive)
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
randomInt(1, 6) // Dice roll: 1-6
randomInt(0, 255) // Color component: 0-255
// Random element from array
function randomPick(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
const colors = ['red', 'green', 'blue'];
randomPick(colors) // Random color
// Shuffle array (Fisher-Yates)
function shuffle(arr) {
const a = [...arr]; // Don't mutate original
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;
}
shuffle([1, 2, 3, 4, 5]) // [3, 1, 5, 2, 4]
// Random hex color
function randomColor() {
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
}
randomColor() // "#3f8a2c"
// Random ID (simple, not crypto-secure)
function randomId(length = 8) {
return Math.random().toString(36).substring(2, 2 + length);
}
randomId() // "x7b2k9f1"
randomId(12) // "a3f8k2j9d1x4"
4. Number Formatting
// Currency
(1234567.89).toLocaleString('en-US', {
style: 'currency',
currency: 'USD'
}) // "$1,234,567.89"
// Compact numbers (1.2K, 3.5M, 1.1B)
function compact(num) {
return new Intl.NumberFormat('en', {
notation: 'compact',
maximumFractionDigits: 1
}).format(num);
}
compact(1500) // "1.5K"
compact(3500000) // "3.5M"
compact(1100000000) // "1.1B"
// Percentage
(0.856).toLocaleString('en-US', {
style: 'percent',
maximumFractionDigits: 1
}) // "85.6%"
// With commas
(1234567).toLocaleString() // "1,234,567"
(1234567.891).toLocaleString(undefined, {
maximumFractionDigits: 2
}) // "1,234,567.89"
// Ordinal (1st, 2nd, 3rd, 4th)
function ordinal(n) {
const s = ['th', 'st', 'nd', 'rd'];
const v = n % 100;
return n + (s[(v - 20) % 10] || s[v] || s[0]);
}
ordinal(1) // "1st"
ordinal(2) // "2nd"
ordinal(3) // "3rd"
ordinal(4) // "4th"
ordinal(11) // "11th"
ordinal(21) // "21st"
ordinal(101) // "101st"
5. Math Shortcuts
// Clamp value between min and max
function clamp(val, min, max) {
return Math.min(Math.max(val, min), max);
}
clamp(5, 0, 10) // 5
clamp(-3, 0, 10) // 0
clamp(15, 0, 10) // 10
// Distance between two numbers
const distance = Math.abs(a - b);
// Map value from one range to another
function mapRange(value, inMin, inMax, outMin, outMax) {
return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
}
mapRange(5, 0, 10, 0, 100) // 50
mapRange(0, 0, 10, 32, 212) // 32 (Celsius to Fahrenheit start)
// Lerp (linear interpolation)
function lerp(start, end, t) {
return start + (end - start) * t;
}
lerp(0, 100, 0.5) // 50
lerp(0, 100, 0.25) // 25
// Round to N decimal places
function roundTo(num, decimals = 2) {
const factor = 10 ** decimals;
return Math.round(num * factor) / factor;
}
roundTo(3.14159, 2) // 3.14
roundTo(3.14159, 4) // 3.1416
// Is number between two values?
function between(num, min, max) {
return num > min && num < max;
}
between(5, 0, 10) // true
between(0, 0, 10) // false (exclusive)
between(10, 0, 10) // false (exclusive)
6. Bitwise Tricks
// Check if number is even/odd (faster than % 2)
num & 1 // 0 = even, 1 = odd
5 & 1 // 1 (odd)
4 & 1 // 0 (even)
// Swap two numbers without temp variable
let a = 10, b = 20;
a ^= b; b ^= a; a ^= b;
// a = 20, b = 10
// Floor a positive number (faster than Math.floor)
~~3.7 // 3
~~-3.7 // -3 (Note: NOT the same as Math.floor for negatives!)
// Check if number is a power of 2
function isPowerOf2(n) {
return n > 0 && (n & (n - 1)) === 0;
}
isPowerOf2(4) // true
isPowerOf2(8) // true
isPowerOf2(6) // false
// Fast multiply by 2 (left shift)
5 << 1 // 10
10 << 2 // 40
// Fast divide by 2 (right shift)
10 >> 1 // 5
20 >> 2 // 5
7. Number Validation
// Is it actually a number?
Number.isFinite(42) // true
Number.isFinite(Infinity) // false
Number.isFinite(NaN) // false
Number.isFinite('42') // false (string!)
Number.isFinite(null) // false
// vs typeof (less reliable)
typeof 42 // 'number'
typeof NaN // 'number' (!!)
typeof Infinity // 'number'
// Is it a safe integer? (within ±2^53)
Number.isSafeInteger(42) // true
Number.isSafeInteger(9007199254740992) // true (max safe int)
Number.isSafeInteger(9007199254740992 + 1) // false (!)
Number.isSafeInteger(0.5) // false (not integer)
// Is it a positive number?
function isPositiveNumber(val) {
return typeof val === 'number' && Number.isFinite(val) && val > 0;
}
isPositiveNumber(42) // true
isPositiveNumber(-1) // false
isPositiveNumber(0) // false
isPositiveNumber('42') // false
isPositiveNumber(NaN) // false
8. Performance Tips
// ❌ Slow
Math.floor(x) // Function call overhead
parseInt(x) // Even slower (parsing logic)
// ✅ Faster (for positive numbers)
~~x // Bitwise NOT NOT
x | 0 // Bitwise OR
x >> 0 // Bitwise right shift
// But be careful:
~~2147483647 // 2147483647 (OK)
~~2147483648 // -2147483648 (overflow! 32-bit limit)
// For most cases, Math.trunc() is the safest fast option
Math.trunc(4.9) // 4
Math.trunc(-4.9) // -4
What number tricks do you use? Share them below!
Follow @armorbreak for more JavaScript content.
Top comments (0)