Note: Math methods work with radians, not degrees. Use ** operator over
Math.pow(). Math.random() is pseudo-random (not cryptographically secure - use
crypto.getRandomValues() for security).
4. Number Precision and Floating Point Issues
Issue
Cause
Example
Solution
Binary Representation
IEEE 754 binary cannot represent some decimals exactly
0.1 + 0.2 !== 0.3
Use epsilon comparison or integer math
Rounding Errors
Accumulated precision loss in calculations
0.1 + 0.2 = 0.30000000000000004
Round to fixed decimals, use libraries (decimal.js)
Large Integer Loss
Integers > 2^53-1 lose precision
9007199254740992 + 1 === 9007199254740992
Use BigInt for large integers
Division by Zero
Returns Infinity (not error)
1 / 0 = Infinity
Check denominator before division
NaN Propagation
Any operation with NaN yields NaN
NaN + 5 = NaN
Validate inputs, use Number.isNaN()
Epsilon Comparison
Float equality unreliable
0.1 + 0.2 === 0.3 // false
Math.abs(a - b) < Number.EPSILON
Example: Floating point precision handling
// Classic floating point problem0.1 + 0.2; // 0.30000000000000004 ❌0.1 + 0.2 === 0.3; // false// Epsilon comparison for floatsfunction almostEqual(a, b, epsilon = Number.EPSILON) { return Math.abs(a - b) < epsilon;}almostEqual(0.1 + 0.2, 0.3); // true ✓// For larger numbers, scale epsilonfunction almostEqualScaled(a, b) { const epsilon = Math.max(Math.abs(a), Math.abs(b)) * Number.EPSILON; return Math.abs(a - b) <= epsilon;}// Round to fixed decimalsfunction roundTo(num, decimals) { const factor = 10 ** decimals; return Math.round(num * factor) / factor;}roundTo(0.1 + 0.2, 1); // 0.3 ✓roundTo(1.005, 2); // 1.01 (beware banker's rounding)// Integer math for currency (cents)// ❌ Don't do this:const price = 0.1 + 0.2; // 0.30000000000000004// ✓ Do this:const priceInCents = 10 + 20; // 30const price = priceInCents / 100; // 0.3// Financial calculationsfunction addCurrency(a, b) { return (a * 100 + b * 100) / 100;}addCurrency(0.1, 0.2); // 0.3 ✓// Large integer precision lossconst maxSafe = Number.MAX_SAFE_INTEGER; // 9007199254740991maxSafe + 1; // 9007199254740992 ✓maxSafe + 2; // 9007199254740992 ❌ (lost precision!)// Check safe integer rangeNumber.isSafeInteger(maxSafe); // trueNumber.isSafeInteger(maxSafe + 1); // trueNumber.isSafeInteger(maxSafe + 2); // false// Division by zero1 / 0; // Infinity (not error!)-1 / 0; // -Infinity0 / 0; // NaN// Check for valid resultfunction safeDivide(a, b) { if (b === 0) return null; return a / b;}// NaN propagationconst result = NaN + 5; // NaNMath.sqrt(-1) * 2; // NaN// Always check NaNfunction safeCalculation(a, b) { const result = a / b; if (Number.isNaN(result)) { throw new Error('Invalid calculation'); } return result;}// Rounding modesMath.round(2.5); // 3Math.round(-2.5); // -2 (rounds towards zero for negatives)Math.floor(2.9); // 2Math.floor(-2.1); // -3 (towards negative infinity)Math.ceil(2.1); // 3Math.ceil(-2.9); // -2 (towards positive infinity)Math.trunc(2.9); // 2Math.trunc(-2.9); // -2 (just removes decimal)// Banker's rounding (round half to even)function bankersRound(num, decimals = 0) { const factor = 10 ** decimals; const n = num * factor; const floor = Math.floor(n); const diff = n - floor; if (diff === 0.5) { return floor % 2 === 0 ? floor / factor : Math.ceil(n) / factor; } return Math.round(n) / factor;}// Comparing with tolerancefunction withinTolerance(a, b, tolerance = 0.001) { return Math.abs(a - b) <= tolerance;}withinTolerance(0.1 + 0.2, 0.3, 0.001); // true// Use decimal libraries for precision// npm install decimal.js// const Decimal = require('decimal.js');// new Decimal(0.1).plus(0.2).equals(0.3); // true
Warning: Never use === for float comparison. Use epsilon tolerance. For currency,
work in cents (integers). Large integers require BigInt. IEEE 754 has inherent precision limits.
5. BigInt Creation and Arithmetic Operations
Feature
Syntax
Description
Example
Literal ES2020
123n
Arbitrary precision integers; append n suffix
9007199254740993n
Constructor
BigInt(value)
Convert number/string to BigInt
BigInt("999")
Addition
a + b
Both operands must be BigInt
10n + 20n = 30n
Subtraction
a - b
Both operands must be BigInt
50n - 20n = 30n
Multiplication
a * b
Both operands must be BigInt
10n * 20n = 200n
Division
a / b
Integer division (rounds towards zero)
10n / 3n = 3n
Remainder
a % b
Modulo operation
10n % 3n = 1n
Exponentiation
a ** b
Power operation; exponent must be non-negative
2n ** 100n
Comparison
< > <= >= ==
Works across BigInt and Number (loose ==)
10n < 20 // true
Bitwise
& | ^ ~ << >>
All bitwise operators supported
5n & 3n = 1n
Type Check
typeof value
Returns "bigint"
typeof 10n === "bigint"
Example: BigInt usage
// Creationconst big1 = 9007199254740993n; // literal with n suffixconst big2 = BigInt(9007199254740993); // constructorconst big3 = BigInt("9007199254740993"); // from string (for very large)// Cannot mix BigInt and Number10n + 20; // ❌ TypeError: Cannot mix BigInt and other types10n + 20n; // ✓ 30n// Convert between typesconst num = 42;const big = BigInt(num); // Number to BigIntconst backToNum = Number(big); // BigInt to Number (may lose precision!)// Arithmetic operations100n + 50n; // 150n100n - 50n; // 50n10n * 20n; // 200n// Division truncates (integer division)10n / 3n; // 3n (not 3.333...)-10n / 3n; // -3n (rounds towards zero)10n % 3n; // 1n (remainder)// Exponentiation2n ** 100n; // huge number2n ** -1n; // ❌ RangeError: exponent must be non-negative// Comparison10n < 20n; // true10n === 10n; // true10n === 10; // false (strict equality - different types)10n == 10; // true (loose equality - coerces)// Mixed comparisons (non-equality)10n < 20; // true ✓10n > 5; // true ✓20n <= 20; // true ✓// Bitwise operationsconst a = 5n; // 0101const b = 3n; // 0011a & b; // 1n (0001)a | b; // 7n (0111)a ^ b; // 6n (0110)~a; // -6n (bitwise NOT)5n << 2n; // 20n (shift left)20n >> 2n; // 5n (shift right)// No unsigned right shift (>>>) for BigInt// Large factorials (no overflow!)function factorial(n) { let result = 1n; for (let i = 2n; i <= n; i++) { result *= i; } return result;}factorial(100n); // huge number (no precision loss!)// Compare with regular number (loses precision)function factorialNumber(n) { let result = 1; for (let i = 2; i <= n; i++) { result *= i; } return result;}factorialNumber(100); // Infinity (overflow!)// Large integer operationsconst maxSafe = BigInt(Number.MAX_SAFE_INTEGER);maxSafe + 1n; // works correctly!maxSafe + 2n; // still correct!// Crypto/hashing with BigIntconst large = 2n ** 256n; // 256-bit number// No fractional BigIntconst frac = 1.5n; // ❌ SyntaxErrorconst fromFloat = BigInt(1.5); // ❌ RangeError// Must be integerconst safe = BigInt(Math.floor(1.5)); // ✓ 1n// Type checkingtypeof 10n; // "bigint"10n instanceof BigInt; // ❌ false (primitives not instances)// Conversion gotchasNumber(2n ** 100n); // Infinity (too large for Number!)// Safe conversion checkfunction safeToNumber(bigint) { const num = Number(bigint); if (!Number.isSafeInteger(num)) { throw new Error('BigInt too large for safe Number conversion'); } return num;}// JSON doesn't support BigIntJSON.stringify({value: 10n}); // ❌ TypeError// Custom JSON serializationJSON.stringify({value: 10n}, (key, value) => typeof value === 'bigint' ? value.toString() : value); // '{"value":"10"}'// Math methods don't work with BigIntMath.max(10n, 20n); // ❌ TypeErrorMath.sqrt(100n); // ❌ TypeError// Must use BigInt operationsfunction maxBigInt(...args) { return args.reduce((max, val) => val > max ? val : max);}maxBigInt(10n, 50n, 30n); // 50n// Practical: microsecond timestampsconst timestamp = BigInt(Date.now()) * 1000n; // microseconds// Practical: precise money calculationsconst cents = 12345n; // $123.45const dollars = Number(cents) / 100; // 123.45
Warning: Cannot mix BigInt with Number in operations. Division truncates. No fractional BigInt.
JSON doesn't support BigInt. Math methods incompatible with BigInt.
6. Number Parsing and Validation
Function
Syntax
Description
Returns
parseInt()
parseInt(string, radix)
Parse string to integer; optional base (2-36); stops at non-digit
Integer or NaN
parseFloat()
parseFloat(string)
Parse string to float; stops at invalid character
Float or NaN
Number()
Number(value)
Convert to number; strict (entire string must be valid)
Number or NaN
Unary Plus
+value
Shorthand for Number(); strict conversion
Number or NaN
isNaN()
isNaN(value)
Global; coerces to number first (avoid)
Boolean
Number.isNaN()
Number.isNaN(value)
Strict; true only if value is NaN (preferred)
Boolean
isFinite()
isFinite(value)
Global; coerces to number first
Boolean
Number.isFinite()
Number.isFinite(value)
Strict; no coercion (preferred)
Boolean
Number.isInteger()
Number.isInteger(value)
Check if integer (no fractional part)
Boolean
Number.isSafeInteger()
Number.isSafeInteger(value)
Check if integer in safe range [-(2^53-1), 2^53-1]
Boolean
Example: Parsing and validation
// parseInt - parses until invalid characterparseInt('123'); // 123parseInt('123.45'); // 123 (stops at decimal)parseInt('123px'); // 123 (stops at 'p')parseInt('abc'); // NaN (no valid digits)parseInt(' 42'); // 42 (trims whitespace)// Always specify radix!parseInt('08'); // 8 (may be octal in old browsers without radix!)parseInt('08', 10); // 8 ✓ (always use radix)// Different basesparseInt('FF', 16); // 255 (hexadecimal)parseInt('1010', 2); // 10 (binary)parseInt('77', 8); // 63 (octal)parseInt('Z', 36); // 35 (max base)// Radix validationparseInt('123', 10); // 123parseInt('123', 2); // 1 (stops at '2', invalid for binary)// parseFloat - decimal parsingparseFloat('123.45'); // 123.45parseFloat('123.45.67'); // 123.45 (stops at second '.')parseFloat('123.45px'); // 123.45 (stops at 'p')parseFloat('.5'); // 0.5parseFloat('5.'); // 5// Scientific notationparseFloat('1.23e10'); // 12300000000parseFloat('1e-5'); // 0.00001// Number() - strict conversionNumber('123'); // 123Number('123.45'); // 123.45Number('123px'); // NaN ❌ (entire string must be valid)Number(' 42 '); // 42 (trims whitespace)Number(''); // 0 (empty string is 0!)Number(' '); // 0 (whitespace only is 0)// Unary plus (shorthand)+'123'; // 123+'123.45'; // 123.45+'123px'; // NaN// Comparison: parseInt vs parseFloat vs Numberconst str = '123.45px';parseInt(str); // 123 (stops at decimal)parseFloat(str); // 123.45 (stops at 'p')Number(str); // NaN (invalid)// Type coercion gotchasNumber(true); // 1Number(false); // 0Number(null); // 0Number(undefined); // NaNNumber([]); // 0 (empty array)Number([5]); // 5 (single element)Number([1, 2]); // NaN (multiple elements)// Validation: isNaN vs Number.isNaNisNaN('hello'); // true (coerces 'hello' to NaN)Number.isNaN('hello'); // false (string is not NaN)Number.isNaN(NaN); // true ✓isNaN(undefined); // true (coerces to NaN)Number.isNaN(undefined); // false (undefined is not NaN)// Rule: Use Number.isNaN() for strict checkingNumber.isNaN(0 / 0); // trueNumber.isNaN(parseFloat('abc')); // true// Validation: isFinite vs Number.isFiniteisFinite('123'); // true (coerces to 123)Number.isFinite('123'); // false (string is not finite number)isFinite(Infinity); // falseNumber.isFinite(Infinity); // falseisFinite(NaN); // falseNumber.isFinite(NaN); // false// Rule: Use Number.isFinite() for strict checking// Integer validationNumber.isInteger(42); // trueNumber.isInteger(42.0); // true (same as 42)Number.isInteger(42.5); // falseNumber.isInteger('42'); // false (no coercion)// Safe integer validationNumber.isSafeInteger(42); // trueNumber.isSafeInteger(Number.MAX_SAFE_INTEGER); // trueNumber.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // falseNumber.isSafeInteger(42.0); // true// Practical validation functionsfunction isValidNumber(value) { return typeof value === 'number' && Number.isFinite(value) && !Number.isNaN(value);}function parseOrDefault(str, defaultValue = 0) { const num = parseFloat(str); return Number.isNaN(num) ? defaultValue : num;}function strictParse(str) { const num = Number(str); if (Number.isNaN(num)) { throw new Error(`Invalid number: ${str}`); } return num;}// Safe parsingfunction safeParse(str) { const trimmed = str.trim(); if (trimmed === '') return null; const num = Number(trimmed); return Number.isNaN(num) ? null : num;}safeParse('123'); // 123safeParse('abc'); // nullsafeParse(''); // null// Parsing with validationfunction parsePositiveInt(str) { const num = parseInt(str, 10); if (Number.isNaN(num) || num <= 0 || !Number.isInteger(num)) { return null; } return num;}// Currency parsingfunction parseCurrency(str) { // Remove currency symbols and commas const cleaned = str.replace(/[$,]/g, ''); const num = parseFloat(cleaned); return Number.isNaN(num) ? null : num;}parseCurrency('$1,234.56'); // 1234.56parseCurrency('€1.234,56'); // requires more complex parsing// Input validationfunction validateInput(input) { // Check if empty if (!input || input.trim() === '') { return {valid: false, error: 'Input required'}; } // Try to parse const num = Number(input); // Check if valid number if (Number.isNaN(num)) { return {valid: false, error: 'Not a valid number'}; } // Check if finite if (!Number.isFinite(num)) { return {valid: false, error: 'Must be finite'}; } return {valid: true, value: num};}
Note: Always specify radix for parseInt(). Use Number.isNaN() and
Number.isFinite() (no coercion) over global versions. Number() strict (entire string),
parseInt/parseFloat lenient (stops at invalid).
Section 12 Summary
Literals: Decimal, binary (0b), octal (0o), hex (0x), scientific (1e6);
numeric separators (1_000_000) for readability; special values: Infinity, -Infinity, NaN
Number methods:isFinite/isInteger/isNaN/isSafeInteger
validation (no coercion); toFixed/toExponential/toPrecision format (return strings);
toString(radix) base conversion
Math object:round/ceil/floor/trunc rounding;
min/max/abs/sign basic; pow/sqrt/cbrt powers/roots; random() [0,1);
trig functions use radians
Precision: IEEE 754 float issues (0.1+0.2≠0.3); use epsilon comparison
(Math.abs(a-b)<Number.EPSILON); work in integers for currency; safe integer range: ±(2^53-1)
BigInt: Arbitrary precision integers with n suffix (123n);
cannot mix with Number; division truncates; no fractional BigInt; use for >2^53-1 integers
Parsing:parseInt(str, radix) lenient (stops at invalid);
parseFloat(str) decimal; Number(value) strict (entire string); always use radix
with parseInt
Validation: Prefer Number.is*() over global versions (no
coercion); isNaN/isFinite/isInteger/isSafeInteger; validate before arithmetic to prevent NaN
propagation