Docs
Module-08-Numbers-Math
14.1 Number Fundamentals
Overview
JavaScript has a single number type that handles both integers and floating-point numbers. Understanding how numbers work, their limitations, and the methods available for working with them is essential for writing reliable code.
Number System in JavaScript
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JavaScript Number Type β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Based on IEEE 754 double-precision 64-bit floating point β
β β
β ββββββββββββ¬ββββββββββββββββ¬βββββββββββββββββββββββββββββββββ β
β β Sign β Exponent β Mantissa β β
β β 1 bit β 11 bits β 52 bits β β
β ββββββββββββ΄ββββββββββββββββ΄βββββββββββββββββββββββββββββββββ β
β β
β Safe Integer Range: -(2^53 - 1) to (2^53 - 1) β
β Max Value: ~1.8 Γ 10^308 β
β Min Value: ~5 Γ 10^-324 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Creating Numbers
// Number literals
let integer = 42;
let negative = -17;
let float = 3.14159;
let scientific = 2.998e8; // 299,800,000
// Special numeric literals
let binary = 0b1010; // 10 in binary
let octal = 0o755; // 493 in octal
let hex = 0xff; // 255 in hexadecimal
// Numeric separators (ES2021)
let billion = 1_000_000_000;
let bytes = 0xff_ff_ff_ff;
// Number constructor
let fromString = Number('42'); // 42
let fromBool = Number(true); // 1
Special Number Values
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Special Number Values β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββ€
β Infinity β Result of division by zero, overflow β
β -Infinity β Negative infinity β
β NaN β "Not a Number" - invalid operation result β
β Number.MAX_VALUEβ Largest representable number β
β Number.MIN_VALUEβ Smallest positive number (closest to 0) β
ββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββ€
β NaN Behavior β NaN !== NaN (NaN is not equal to itself!) β
ββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββ
// Infinity
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Infinity + 1); // Infinity
console.log(Infinity - Infinity); // NaN
// NaN (Not a Number)
console.log(0 / 0); // NaN
console.log('hello' * 2); // NaN
console.log(Math.sqrt(-1)); // NaN
// NaN quirks
console.log(NaN === NaN); // false (!)
console.log(typeof NaN); // "number" (!)
Number Methods
Checking Methods
| Method | Description | Example |
|---|---|---|
Number.isNaN() | Checks if value is NaN | Number.isNaN(NaN) β true |
Number.isFinite() | Checks if value is finite | Number.isFinite(42) β true |
Number.isInteger() | Checks if value is integer | Number.isInteger(3.0) β true |
Number.isSafeInteger() | Checks safe integer range | Number.isSafeInteger(2**53) β false |
// isNaN vs global isNaN
isNaN('hello'); // true (coerces to NaN first)
Number.isNaN('hello'); // false (no coercion)
Number.isNaN(NaN); // true
// isFinite
Number.isFinite(42); // true
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
// isInteger
Number.isInteger(5); // true
Number.isInteger(5.0); // true
Number.isInteger(5.5); // false
// isSafeInteger
Number.isSafeInteger(42); // true
Number.isSafeInteger(2 ** 53); // false
Number.isSafeInteger(2 ** 53 - 1); // true
Conversion Methods
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Number Conversion Methods β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββ€
β toString(radix) β Convert to string with optional base β
β toFixed(digits) β Fixed decimal places β
β toPrecision(sig) β Total significant digits β
β toExponential(d) β Scientific notation β
β valueOf() β Primitive number value β
ββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββ
let num = 255;
// toString with different bases
num.toString(); // "255"
num.toString(2); // "11111111" (binary)
num.toString(8); // "377" (octal)
num.toString(16); // "ff" (hexadecimal)
// Decimal formatting
let pi = 3.14159265;
pi.toFixed(2); // "3.14"
pi.toFixed(4); // "3.1416" (rounded)
pi.toFixed(0); // "3"
// Precision
let big = 123456.789;
big.toPrecision(4); // "1.235e+5"
big.toPrecision(6); // "123457"
big.toPrecision(10); // "123456.7890"
// Scientific notation
let sci = 123456;
sci.toExponential(2); // "1.23e+5"
sci.toExponential(4); // "1.2346e+5"
Parsing Numbers
// parseInt - parses integers
parseInt('42'); // 42
parseInt('42.9'); // 42 (ignores decimal)
parseInt('42px'); // 42 (stops at non-digit)
parseInt('px42'); // NaN (must start with digit)
parseInt('0xFF'); // 255 (detects hex)
parseInt('1010', 2); // 10 (binary)
parseInt('ff', 16); // 255 (hexadecimal)
// parseFloat - parses floating-point
parseFloat('3.14'); // 3.14
parseFloat('3.14.15'); // 3.14 (stops at second dot)
parseFloat(' 3.14 '); // 3.14 (trims whitespace)
parseFloat('3.14e2'); // 314
// Number() vs parseInt/parseFloat
Number('42px'); // NaN (strict)
parseInt('42px'); // 42 (lenient)
Number(''); // 0
parseInt(''); // NaN
Number(null); // 0
parseInt(null); // NaN
Number(true); // 1
parseInt(true); // NaN
Floating-Point Precision
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Floating-Point Precision Issues β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 0.1 + 0.2 = 0.30000000000000004 (not 0.3!) β
β β
β Why? Binary can't exactly represent all decimal fractions β
β Just like 1/3 = 0.333... in decimal β
β β
β Solution: Use epsilon comparison or integer arithmetic β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// The classic problem
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false (!)
// Solution 1: Epsilon comparison
function almostEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
almostEqual(0.1 + 0.2, 0.3); // true
// Solution 2: Round to fixed decimals
function roundTo(num, decimals) {
return Number(num.toFixed(decimals));
}
roundTo(0.1 + 0.2, 10); // 0.3
// Solution 3: Integer arithmetic (for currency)
// Work in cents instead of dollars
let priceInCents = 199 + 299; // 498 cents
let priceInDollars = priceInCents / 100; // $4.98
BigInt for Large Integers
// BigInt for integers beyond safe range
const big = 9007199254740991n; // BigInt literal
const alsoBig = BigInt('9007199254740991');
// Operations
big + 1n; // 9007199254740992n
big * 2n; // 18014398509481982n
big / 3n; // 3002399751580330n (truncates)
// Cannot mix BigInt and Number
// big + 1; // TypeError!
big + BigInt(1); // Works
// Comparison works
big > 1000; // true
big === 9007199254740991n; // true
// Converting
Number(big); // 9007199254740991 (may lose precision)
String(big); // "9007199254740991"
Number Constants
| Constant | Value | Description |
|---|---|---|
Number.MAX_VALUE | ~1.8e308 | Largest representable number |
Number.MIN_VALUE | ~5e-324 | Smallest positive number |
Number.MAX_SAFE_INTEGER | 2^53 - 1 | Largest safe integer |
Number.MIN_SAFE_INTEGER | -(2^53 - 1) | Smallest safe integer |
Number.POSITIVE_INFINITY | Infinity | Positive infinity |
Number.NEGATIVE_INFINITY | -Infinity | Negative infinity |
Number.NaN | NaN | Not a Number |
Number.EPSILON | ~2.2e-16 | Smallest difference between numbers |
Common Patterns
// Clamp a number to a range
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
clamp(150, 0, 100); // 100
clamp(-50, 0, 100); // 0
// Check if a value is numeric
function isNumeric(value) {
return !isNaN(parseFloat(value)) && isFinite(value);
}
// Format number with commas
function formatWithCommas(num) {
return num.toLocaleString();
}
formatWithCommas(1234567); // "1,234,567"
// Currency formatting
function formatCurrency(amount, currency = 'USD') {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency,
}).format(amount);
}
formatCurrency(1234.56); // "$1,234.56"
// Percentage formatting
function formatPercent(decimal) {
return new Intl.NumberFormat('en-US', {
style: 'percent',
minimumFractionDigits: 1,
}).format(decimal);
}
formatPercent(0.1234); // "12.3%"
Key Takeaways
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Number Fundamentals β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 1. JavaScript uses IEEE 754 double-precision floats β
β 2. Special values: Infinity, -Infinity, NaN β
β 3. NaN !== NaN (use Number.isNaN() to check) β
β 4. Floating-point math can be imprecise (0.1 + 0.2) β
β 5. Use BigInt for integers beyond safe integer range β
β 6. Number.isNaN() is safer than global isNaN() β
β 7. parseInt/parseFloat are lenient; Number() is strict β
β 8. Use Intl.NumberFormat for locale-aware formatting β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ