Numbers, Math, and BigInt Operations

1. Number Types and Numeric Literals

Type/Literal Syntax Description Example
Decimal Integer 123 Base 10 integer; most common form 42, -17, 0
Decimal Float 1.23 Floating point number; IEEE 754 double precision (64-bit) 3.14, -0.5, 0.1
Scientific Notation 1e10 Exponent form: number × 10^exponent 1e6 (1000000), 5e-3 (0.005)
Binary ES2015 0b101 Base 2; prefix 0b or 0B; digits 0-1 0b1010 (10), 0b1111 (15)
Octal ES2015 0o17 Base 8; prefix 0o or 0O; digits 0-7 0o10 (8), 0o77 (63)
Hexadecimal 0xFF Base 16; prefix 0x or 0X; digits 0-9, A-F 0xFF (255), 0x1A (26)
Numeric Separators ES2021 1_000_000 Underscores for readability; ignored by engine 1_000, 0xFF_FF, 0b1010_1010
Special Values Infinity, -Infinity, NaN Special numeric values; NaN ≠ NaN 1/0, -1/0, 0/0
Signed Zero +0, -0 IEEE 754 has both; usually treated as equal -0 === +0 // true

Example: Numeric literal forms

// Decimal integers
const dec = 42;
const negative = -17;
const zero = 0;

// Decimal floats
const pi = 3.14159;
const small = 0.0001;
const leading = .5; // 0.5 (avoid - use 0.5)
const trailing = 5.; // 5 (avoid - use 5.0 or 5)

// Scientific notation
const million = 1e6; // 1000000
const billion = 1e9; // 1000000000
const tiny = 5e-3; // 0.005
const planck = 6.62607015e-34;

// Binary (base 2)
const binary = 0b1010; // 10
const flags = 0b11111111; // 255
const mask = 0b1100; // 12

// Octal (base 8)
const octal = 0o17; // 15
const permissions = 0o755; // 493 (rwxr-xr-x)

// Hexadecimal (base 16)
const hex = 0xFF; // 255
const color = 0xFF5733; // 16734003
const byte = 0xAB; // 171

// Mixed case OK
const HEX = 0XFF; // 255
const BIN = 0B1010; // 10

// Numeric separators (readability)
const oneMillion = 1_000_000;
const billion = 1_000_000_000;
const hexColor = 0xFF_55_33;
const binary8bit = 0b1111_0000;
const creditCard = 1234_5678_9012_3456;

// Separators anywhere except start/end
const amount = 123_456.789_012;

// Special values
const inf = Infinity;
const negInf = -Infinity;
const notANumber = NaN;

1 / 0; // Infinity
-1 / 0; // -Infinity
0 / 0; // NaN
Math.sqrt(-1); // NaN

// NaN is unique
NaN === NaN; // false ❌
isNaN(NaN); // true ✓
Number.isNaN(NaN); // true ✓ (preferred)

// Signed zeros
+0 === -0; // true
Object.is(+0, -0); // false (can distinguish)

1 / +0; // Infinity
1 / -0; // -Infinity

// Type checking
typeof 42; // "number"
typeof 3.14; // "number"
typeof NaN; // "number" (yes, really!)
typeof Infinity; // "number"

// Number range
Number.MAX_VALUE; // ~1.79e308
Number.MIN_VALUE; // ~5e-324 (smallest positive)
Number.MAX_SAFE_INTEGER; // 2^53 - 1 (9007199254740991)
Number.MIN_SAFE_INTEGER; // -(2^53 - 1)
Note: JavaScript numbers are 64-bit IEEE 754 floats. Use numeric separators for readability. Prefer Number.isNaN() over isNaN(). Safe integer range: ±2^53-1.

2. Number Methods and Constants

Method/Property Syntax Description Returns
isFinite() Number.isFinite(value) Check if finite number (not Infinity/NaN); no coercion Boolean
isInteger() Number.isInteger(value) Check if integer (no fractional part) Boolean
isNaN() Number.isNaN(value) Check if NaN; no coercion (safer than global isNaN()) Boolean
isSafeInteger() Number.isSafeInteger(value) Check if integer in safe range [-(2^53-1), 2^53-1] Boolean
toExponential() num.toExponential(digits) Scientific notation string; optional decimal digits String
toFixed() num.toFixed(digits) Fixed decimal places; rounds; 0-20 digits String
toPrecision() num.toPrecision(precision) Specified total significant digits; 1-21 String
toString() num.toString(radix) String representation; optional base (2-36) String
valueOf() num.valueOf() Primitive value; rarely needed Number
toLocaleString() num.toLocaleString(locale, options) Locale-aware formatting; currency, percentages, units String
Constant Value Description Use Case
EPSILON ~2.22e-16 Smallest difference between 1 and next representable number Float comparison tolerance
MAX_VALUE ~1.79e308 Largest positive number Range checking
MIN_VALUE ~5e-324 Smallest positive number (near zero) Precision limits
MAX_SAFE_INTEGER 9007199254740991 2^53 - 1; largest safe integer Integer arithmetic bounds
MIN_SAFE_INTEGER -9007199254740991 -(2^53 - 1); smallest safe integer Integer arithmetic bounds
POSITIVE_INFINITY Infinity Positive infinity; same as global Infinity Overflow detection
NEGATIVE_INFINITY -Infinity Negative infinity Underflow detection
NaN NaN Not-a-Number; same as global NaN Invalid operations

Example: Number methods and constants

// Type checking methods
Number.isFinite(42); // true
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Number.isFinite('42'); // false (no coercion!)

// Compare: global isFinite() coerces
isFinite('42'); // true (coerces to 42)
Number.isFinite('42'); // false (no coercion)

Number.isInteger(42); // true
Number.isInteger(42.0); // true (same as 42)
Number.isInteger(42.5); // false
Number.isInteger('42'); // false

Number.isNaN(NaN); // true
Number.isNaN(42); // false
Number.isNaN('hello'); // false (no coercion!)

// Compare: global isNaN() coerces
isNaN('hello'); // true (coerces to NaN)
Number.isNaN('hello'); // false (no coercion)

Number.isSafeInteger(42); // true
Number.isSafeInteger(9007199254740991); // true (MAX_SAFE_INTEGER)
Number.isSafeInteger(9007199254740992); // false (too large)
Number.isSafeInteger(42.5); // false (not integer)

// Formatting methods
const num = 123.456;

num.toFixed(2); // "123.46" (rounds)
num.toFixed(0); // "123"
num.toFixed(5); // "123.45600"

num.toExponential(2); // "1.23e+2"
(1234.5).toExponential(); // "1.2345e+3"

num.toPrecision(4); // "123.5"
num.toPrecision(2); // "1.2e+2" (switches to exponential)
num.toPrecision(10); // "123.4560000"

// Base conversion
(255).toString(); // "255"
(255).toString(16); // "ff" (hex)
(255).toString(2); // "11111111" (binary)
(255).toString(8); // "377" (octal)
(255).toString(36); // "73" (max base)

// Locale formatting
const price = 1234.56;
price.toLocaleString('en-US', {
    style: 'currency',
    currency: 'USD'
}); // "$1,234.56"

price.toLocaleString('de-DE', {
    style: 'currency',
    currency: 'EUR'
}); // "1.234,56 €"

const percent = 0.755;
percent.toLocaleString('en-US', {
    style: 'percent',
    minimumFractionDigits: 1
}); // "75.5%"

// Constants
Number.EPSILON; // 2.220446049250313e-16
Number.MAX_VALUE; // 1.7976931348623157e+308
Number.MIN_VALUE; // 5e-324
Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MIN_SAFE_INTEGER; // -9007199254740991

// Safe integer range check
function isSafeArithmetic(a, b) {
    const result = a + b;
    return Number.isSafeInteger(a) &&
           Number.isSafeInteger(b) &&
           Number.isSafeInteger(result);
}

// Floating point comparison with EPSILON
function almostEqual(a, b) {
    return Math.abs(a - b) < Number.EPSILON;
}

almostEqual(0.1 + 0.2, 0.3); // true
0.1 + 0.2 === 0.3; // false ❌

// Format large numbers
const large = 1234567890;
large.toLocaleString('en-US'); // "1,234,567,890"

// Scientific notation
(0.0000001).toExponential(); // "1e-7"
(10000000).toExponential(); // "1e+7"

// Precision control
const value = 123.456789;
value.toFixed(2); // "123.46"
value.toPrecision(5); // "123.46"
parseFloat(value.toFixed(2)); // 123.46 (back to number)
Warning: toFixed(), toExponential(), toPrecision() return strings. Use Number.is*() over global versions (no coercion). Safe integers: ±(2^53-1).

3. Math Object Methods and Constants

Method Description Example Result
abs(x) Absolute value Math.abs(-5) 5
ceil(x) Round up to integer Math.ceil(4.1) 5
floor(x) Round down to integer Math.floor(4.9) 4
round(x) Round to nearest integer Math.round(4.5) 5
trunc(x) Remove fractional part Math.trunc(4.9) 4
sign(x) Sign: -1, 0, or 1 Math.sign(-5) -1
min(...args) Smallest of arguments Math.min(2, 5, 1) 1
max(...args) Largest of arguments Math.max(2, 5, 1) 5
pow(x, y) x to power y; use ** operator Math.pow(2, 3) 8
sqrt(x) Square root Math.sqrt(16) 4
cbrt(x) Cube root Math.cbrt(27) 3
exp(x) e^x (Euler's number) Math.exp(1) ~2.718
log(x) Natural logarithm (base e) Math.log(Math.E) 1
log10(x) Base 10 logarithm Math.log10(100) 2
log2(x) Base 2 logarithm Math.log2(8) 3
random() Random [0, 1); pseudo-random Math.random() 0.123...
Trigonometry Description Hyperbolic Description
sin(x) Sine (radians) sinh(x) Hyperbolic sine
cos(x) Cosine (radians) cosh(x) Hyperbolic cosine
tan(x) Tangent (radians) tanh(x) Hyperbolic tangent
asin(x) Arcsine asinh(x) Inverse hyperbolic sine
acos(x) Arccosine acosh(x) Inverse hyperbolic cosine
atan(x) Arctangent atanh(x) Inverse hyperbolic tangent
atan2(y, x) Angle from origin to (x,y) hypot(...args) √(x²+y²+...) - Euclidean norm
Constant Value Description Formula
E ~2.718 Euler's number Base of natural logarithms
PI ~3.14159 Pi (π) Circle circumference / diameter
LN2 ~0.693 ln(2) Natural log of 2
LN10 ~2.303 ln(10) Natural log of 10
LOG2E ~1.443 log₂(e) Base 2 log of e
LOG10E ~0.434 log₁₀(e) Base 10 log of e
SQRT1_2 ~0.707 √(1/2) Square root of 0.5
SQRT2 ~1.414 √2 Square root of 2

Example: Math operations

// Rounding
Math.round(4.5); // 5
Math.round(4.4); // 4
Math.round(-4.5); // -4 (rounds to nearest even)

Math.ceil(4.1); // 5 (always up)
Math.floor(4.9); // 4 (always down)
Math.trunc(4.9); // 4 (remove decimal)

// Difference: floor vs trunc with negatives
Math.floor(-4.1); // -5 (down = more negative)
Math.trunc(-4.1); // -4 (just removes decimal)

// Absolute value and sign
Math.abs(-5); // 5
Math.abs(5); // 5

Math.sign(-5); // -1
Math.sign(0); // 0
Math.sign(5); // 1

// Min/Max
Math.min(5, 2, 8, 1); // 1
Math.max(5, 2, 8, 1); // 8

// With arrays (spread)
const nums = [5, 2, 8, 1];
Math.min(...nums); // 1
Math.max(...nums); // 8

// Power and roots
Math.pow(2, 3); // 8
2 ** 3; // 8 (exponentiation operator - preferred)

Math.sqrt(16); // 4
Math.sqrt(2); // 1.4142135623730951
Math.cbrt(27); // 3
Math.cbrt(8); // 2

// Logarithms
Math.log(Math.E); // 1 (natural log)
Math.log10(100); // 2
Math.log2(8); // 3

// Exponential
Math.exp(1); // 2.718281828459045 (e^1)
Math.exp(2); // 7.389... (e^2)

// Random numbers
Math.random(); // 0 <= x < 1

// Random integer in range [min, max]
function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
randomInt(1, 6); // dice roll (1-6)

// Random from array
function randomItem(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
}

// Trigonometry (radians!)
Math.sin(Math.PI / 2); // 1
Math.cos(0); // 1
Math.tan(Math.PI / 4); // ~1

// Degrees to radians
function toRadians(degrees) {
    return degrees * Math.PI / 180;
}

// Radians to degrees
function toDegrees(radians) {
    return radians * 180 / Math.PI;
}

Math.sin(toRadians(30)); // 0.5

// atan2 - angle from origin to point
Math.atan2(1, 1); // π/4 (45 degrees)
Math.atan2(1, 0); // π/2 (90 degrees)

// Hypotenuse (Pythagorean)
Math.hypot(3, 4); // 5 (3² + 4² = 5²)
Math.hypot(1, 1); // √2 (1.414...)

// Distance between 2D points
function distance(x1, y1, x2, y2) {
    return Math.hypot(x2 - x1, y2 - y1);
}

// Constants
Math.PI; // 3.141592653589793
Math.E; // 2.718281828459045

// Circle calculations
const radius = 5;
const circumference = 2 * Math.PI * radius; // 31.4...
const area = Math.PI * radius ** 2; // 78.5...

// Practical uses
// 1. Clamp value to range
function clamp(value, min, max) {
    return Math.min(Math.max(value, min), max);
}

// 2. Linear interpolation
function lerp(start, end, t) {
    return start + (end - start) * t;
}

// 3. Map value from one range to another
function map(value, inMin, inMax, outMin, outMax) {
    return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}

// 4. Round to decimal places
function roundTo(num, places) {
    const factor = 10 ** places;
    return Math.round(num * factor) / factor;
}
roundTo(3.14159, 2); // 3.14
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 problem
0.1 + 0.2; // 0.30000000000000004 ❌
0.1 + 0.2 === 0.3; // false

// Epsilon comparison for floats
function almostEqual(a, b, epsilon = Number.EPSILON) {
    return Math.abs(a - b) < epsilon;
}

almostEqual(0.1 + 0.2, 0.3); // true ✓

// For larger numbers, scale epsilon
function almostEqualScaled(a, b) {
    const epsilon = Math.max(Math.abs(a), Math.abs(b)) * Number.EPSILON;
    return Math.abs(a - b) <= epsilon;
}

// Round to fixed decimals
function 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; // 30
const price = priceInCents / 100; // 0.3

// Financial calculations
function addCurrency(a, b) {
    return (a * 100 + b * 100) / 100;
}
addCurrency(0.1, 0.2); // 0.3 ✓

// Large integer precision loss
const maxSafe = Number.MAX_SAFE_INTEGER; // 9007199254740991

maxSafe + 1; // 9007199254740992 ✓
maxSafe + 2; // 9007199254740992 ❌ (lost precision!)

// Check safe integer range
Number.isSafeInteger(maxSafe); // true
Number.isSafeInteger(maxSafe + 1); // true
Number.isSafeInteger(maxSafe + 2); // false

// Division by zero
1 / 0; // Infinity (not error!)
-1 / 0; // -Infinity
0 / 0; // NaN

// Check for valid result
function safeDivide(a, b) {
    if (b === 0) return null;
    return a / b;
}

// NaN propagation
const result = NaN + 5; // NaN
Math.sqrt(-1) * 2; // NaN

// Always check NaN
function safeCalculation(a, b) {
    const result = a / b;
    if (Number.isNaN(result)) {
        throw new Error('Invalid calculation');
    }
    return result;
}

// Rounding modes
Math.round(2.5); // 3
Math.round(-2.5); // -2 (rounds towards zero for negatives)

Math.floor(2.9); // 2
Math.floor(-2.1); // -3 (towards negative infinity)

Math.ceil(2.1); // 3
Math.ceil(-2.9); // -2 (towards positive infinity)

Math.trunc(2.9); // 2
Math.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 tolerance
function 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

// Creation
const big1 = 9007199254740993n; // literal with n suffix
const big2 = BigInt(9007199254740993); // constructor
const big3 = BigInt("9007199254740993"); // from string (for very large)

// Cannot mix BigInt and Number
10n + 20; // ❌ TypeError: Cannot mix BigInt and other types
10n + 20n; // ✓ 30n

// Convert between types
const num = 42;
const big = BigInt(num); // Number to BigInt
const backToNum = Number(big); // BigInt to Number (may lose precision!)

// Arithmetic operations
100n + 50n; // 150n
100n - 50n; // 50n
10n * 20n; // 200n

// Division truncates (integer division)
10n / 3n; // 3n (not 3.333...)
-10n / 3n; // -3n (rounds towards zero)

10n % 3n; // 1n (remainder)

// Exponentiation
2n ** 100n; // huge number
2n ** -1n; // ❌ RangeError: exponent must be non-negative

// Comparison
10n < 20n; // true
10n === 10n; // true
10n === 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 operations
const a = 5n; // 0101
const b = 3n; // 0011

a & 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 operations
const maxSafe = BigInt(Number.MAX_SAFE_INTEGER);
maxSafe + 1n; // works correctly!
maxSafe + 2n; // still correct!

// Crypto/hashing with BigInt
const large = 2n ** 256n; // 256-bit number

// No fractional BigInt
const frac = 1.5n; // ❌ SyntaxError
const fromFloat = BigInt(1.5); // ❌ RangeError

// Must be integer
const safe = BigInt(Math.floor(1.5)); // ✓ 1n

// Type checking
typeof 10n; // "bigint"
10n instanceof BigInt; // ❌ false (primitives not instances)

// Conversion gotchas
Number(2n ** 100n); // Infinity (too large for Number!)

// Safe conversion check
function 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 BigInt
JSON.stringify({value: 10n}); // ❌ TypeError

// Custom JSON serialization
JSON.stringify({value: 10n}, (key, value) =>
    typeof value === 'bigint' ? value.toString() : value
); // '{"value":"10"}'

// Math methods don't work with BigInt
Math.max(10n, 20n); // ❌ TypeError
Math.sqrt(100n); // ❌ TypeError

// Must use BigInt operations
function maxBigInt(...args) {
    return args.reduce((max, val) => val > max ? val : max);
}
maxBigInt(10n, 50n, 30n); // 50n

// Practical: microsecond timestamps
const timestamp = BigInt(Date.now()) * 1000n; // microseconds

// Practical: precise money calculations
const cents = 12345n; // $123.45
const 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 character
parseInt('123'); // 123
parseInt('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 bases
parseInt('FF', 16); // 255 (hexadecimal)
parseInt('1010', 2); // 10 (binary)
parseInt('77', 8); // 63 (octal)
parseInt('Z', 36); // 35 (max base)

// Radix validation
parseInt('123', 10); // 123
parseInt('123', 2); // 1 (stops at '2', invalid for binary)

// parseFloat - decimal parsing
parseFloat('123.45'); // 123.45
parseFloat('123.45.67'); // 123.45 (stops at second '.')
parseFloat('123.45px'); // 123.45 (stops at 'p')
parseFloat('.5'); // 0.5
parseFloat('5.'); // 5

// Scientific notation
parseFloat('1.23e10'); // 12300000000
parseFloat('1e-5'); // 0.00001

// Number() - strict conversion
Number('123'); // 123
Number('123.45'); // 123.45
Number('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 Number
const str = '123.45px';
parseInt(str); // 123 (stops at decimal)
parseFloat(str); // 123.45 (stops at 'p')
Number(str); // NaN (invalid)

// Type coercion gotchas
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
Number([]); // 0 (empty array)
Number([5]); // 5 (single element)
Number([1, 2]); // NaN (multiple elements)

// Validation: isNaN vs Number.isNaN
isNaN('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 checking
Number.isNaN(0 / 0); // true
Number.isNaN(parseFloat('abc')); // true

// Validation: isFinite vs Number.isFinite
isFinite('123'); // true (coerces to 123)
Number.isFinite('123'); // false (string is not finite number)

isFinite(Infinity); // false
Number.isFinite(Infinity); // false

isFinite(NaN); // false
Number.isFinite(NaN); // false

// Rule: Use Number.isFinite() for strict checking

// Integer validation
Number.isInteger(42); // true
Number.isInteger(42.0); // true (same as 42)
Number.isInteger(42.5); // false
Number.isInteger('42'); // false (no coercion)

// Safe integer validation
Number.isSafeInteger(42); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false
Number.isSafeInteger(42.0); // true

// Practical validation functions
function 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 parsing
function safeParse(str) {
    const trimmed = str.trim();
    if (trimmed === '') return null;
    
    const num = Number(trimmed);
    return Number.isNaN(num) ? null : num;
}

safeParse('123'); // 123
safeParse('abc'); // null
safeParse(''); // null

// Parsing with validation
function parsePositiveInt(str) {
    const num = parseInt(str, 10);
    if (Number.isNaN(num) || num <= 0 || !Number.isInteger(num)) {
        return null;
    }
    return num;
}

// Currency parsing
function 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.56
parseCurrency('€1.234,56'); // requires more complex parsing

// Input validation
function 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