Welcome back! 👋 In the previous lesson, you mastered the Math object. Now let's go deep on something you've been using since lesson one — Numbers — and understand how they really work in JavaScript!
Numbers in JavaScript are more nuanced than they appear. From floating point surprises to parsing strings, from formatting currency to checking if a value is actually a number — the Number object and its methods give you complete control. Understanding this deeply will save you from subtle bugs that trip up even experienced developers.
Let's master it completely!
How JavaScript Stores Numbers
JavaScript uses a single number type — IEEE 754 double-precision floating-point — for all numbers. There's no separate int or float type like other languages.
console.log(typeof 42); // "number"
console.log(typeof 3.14); // "number"
console.log(typeof -7); // "number"
console.log(typeof Infinity); // "number"
console.log(typeof NaN); // "number" — yes, NaN is a number type!This means integers and decimals are the same type under the hood — which leads to some important quirks.
The Floating Point Problem
This is the most famous JavaScript gotcha — and it trips up developers at every level.
// ❌ You'd expect this to be 0.3 — it's not!
console.log(0.1 + 0.2); // 0.30000000000000004
// More examples
console.log(0.1 + 0.2 === 0.3); // false ❌
console.log(1.1 + 2.2); // 3.3000000000000003
console.log(0.3 - 0.1); // 0.19999999999999998This happens because binary floating-point can't represent 0.1 exactly — just like you can't write 1/3 as a finite decimal.
How to Fix It
// ✅ Method 1: Use toFixed() and parseFloat
let result = parseFloat((0.1 + 0.2).toFixed(2));
console.log(result); // 0.3
console.log(result === 0.3); // true ✅
// ✅ Method 2: Work in integers (paise/cents)
// Store ₹100.50 as 10050 paise — do all math as integers
let price1 = 10; // 10 paise = ₹0.10
let price2 = 20; // 20 paise = ₹0.20
let sum = price1 + price2; // 30 paise = ₹0.30 ✅
console.log(sum / 100); // 0.3 ✅
// ✅ Method 3: Use Number.EPSILON for comparisons
function isEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(isEqual(0.1 + 0.2, 0.3)); // true ✅Number Limits and Special Values
// Largest safe integer JavaScript can represent exactly
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 (2^53 - 1)
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
// Largest and smallest finite numbers
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324 (closest to 0, not negative!)
// Special values
console.log(Number.POSITIVE_INFINITY); // Infinity
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(Number.NaN); // NaN
console.log(Number.EPSILON); // 2.220446049250313e-16Infinity and -Infinity
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Infinity + 1); // Infinity
console.log(Infinity - Infinity); // NaN
// Check for infinity
console.log(isFinite(1000)); // true
console.log(isFinite(Infinity)); // false
console.log(isFinite(NaN)); // falseNaN — Not a Number
NaN is a special value that results from invalid numeric operations.
console.log(0 / 0); // NaN
console.log("hello" * 2); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(parseInt("abc")); // NaN
console.log(undefined + 1); // NaNChecking Numbers
Number.isNaN() — Is it NaN?
// ✅ Number.isNaN() — strict, only true for actual NaN
console.log(Number.isNaN(NaN)); // true ✅
console.log(Number.isNaN("hello")); // false ✅ (it's a string, not NaN)
console.log(Number.isNaN(undefined)); // false ✅
// ⚠️ Global isNaN() — converts first, then checks — can be misleading!
console.log(isNaN("hello")); // true — converts "hello" to NaN first
console.log(isNaN(undefined)); // true — converts undefined to NaN first
// ✅ Always prefer Number.isNaN() over global isNaN()Number.isFinite() — Is it a finite number?
console.log(Number.isFinite(100)); // true
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(-Infinity)); // false
console.log(Number.isFinite(NaN)); // false
console.log(Number.isFinite("100")); // false — string, not a numberNumber.isInteger() — Is it a whole number?
console.log(Number.isInteger(42)); // true
console.log(Number.isInteger(42.0)); // true (42.0 === 42 in JS)
console.log(Number.isInteger(42.5)); // false
console.log(Number.isInteger("42")); // false — string
console.log(Number.isInteger(Infinity)); // falseNumber.isSafeInteger() — Can it be represented exactly?
console.log(Number.isSafeInteger(42)); // true
console.log(Number.isSafeInteger(9007199254740991)); // true (MAX_SAFE)
console.log(Number.isSafeInteger(9007199254740992)); // false (too large!)
console.log(Number.isSafeInteger(3.5)); // falseConverting Strings to Numbers
parseInt() — String to Integer
Parses a string and returns an integer. Stops at the first non-numeric character.
console.log(parseInt("42")); // 42
console.log(parseInt("42.9")); // 42 — drops decimal
console.log(parseInt("42px")); // 42 — stops at 'p'
console.log(parseInt(" 42 ")); // 42 — trims whitespace
console.log(parseInt("abc")); // NaN — no leading number
console.log(parseInt("12abc34")); // 12 — stops at 'a'parseInt() with Radix (Base)
Always pass the radix (base) as the second argument.
console.log(parseInt("ff", 16)); // 255 — hexadecimal
console.log(parseInt("11", 2)); // 3 — binary
console.log(parseInt("77", 8)); // 63 — octal
console.log(parseInt("42", 10)); // 42 — decimal (always specify!)parseFloat() — String to Decimal
Parses a string and returns a floating-point number.
console.log(parseFloat("3.14")); // 3.14
console.log(parseFloat("3.14abc")); // 3.14 — stops at 'a'
console.log(parseFloat(" 3.14 ")); // 3.14 — trims whitespace
console.log(parseFloat("abc")); // NaN
console.log(parseFloat("3.14.15")); // 3.14 — stops at second '.'Number() Constructor — Strict Conversion
Converts a value to a number. Stricter than parseInt/parseFloat.
console.log(Number("42")); // 42
console.log(Number("3.14")); // 3.14
console.log(Number("42px")); // NaN — doesn't ignore trailing chars
console.log(Number("")); // 0
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
console.log(Number(" 42 ")); // 42 — trims whitespaceComparison — parseInt vs parseFloat vs Number
let inputs = ["42", "3.14", "42px", "px42", "", " 10 ", true, null];
inputs.forEach(val => {
console.log(
`${String(val).padEnd(10)} | parseInt: ${String(parseInt(val)).padEnd(6)} | parseFloat: ${String(parseFloat(val)).padEnd(8)} | Number: ${Number(val)}`
);
});
// Output:
// 42 | parseInt: 42 | parseFloat: 42 | Number: 42
// 3.14 | parseInt: 3 | parseFloat: 3.14 | Number: 3.14
// 42px | parseInt: 42 | parseFloat: 42 | Number: NaN
// px42 | parseInt: NaN | parseFloat: NaN | Number: NaN
// | parseInt: NaN | parseFloat: NaN | Number: 0
// 10 | parseInt: 10 | parseFloat: 10 | Number: 10
// true | parseInt: NaN | parseFloat: NaN | Number: 1
// null | parseInt: NaN | parseFloat: NaN | Number: 0Converting Numbers to Strings
toString() — Number to String
let n = 255;
console.log(n.toString()); // "255" — decimal (default)
console.log(n.toString(2)); // "11111111" — binary
console.log(n.toString(8)); // "377" — octal
console.log(n.toString(16)); // "ff" — hexadecimal
// Practical: zero-pad a number
let id = 7;
console.log(id.toString().padStart(4, "0")); // "0007"toFixed() — Fixed Decimal Places
Returns a string with a specified number of decimal places.
let price = 1234.5678;
console.log(price.toFixed(0)); // "1235" — no decimals (rounded)
console.log(price.toFixed(2)); // "1234.57" — 2 decimal places
console.log(price.toFixed(4)); // "1234.5678"
console.log(price.toFixed(6)); // "1234.567800" — pads with zeros
// ⚠️ Returns a STRING — convert back if you need a number
console.log(typeof price.toFixed(2)); // "string"
console.log(parseFloat(price.toFixed(2))); // 1234.57 (number)toPrecision() — Significant Digits
Returns a string with a specified total number of significant digits.
let n = 123.456;
console.log(n.toPrecision(4)); // "123.5" — 4 significant digits
console.log(n.toPrecision(5)); // "123.46" — 5 significant digits
console.log(n.toPrecision(7)); // "123.4560"
console.log(n.toPrecision(2)); // "1.2e+2" — scientific notation
let small = 0.000123;
console.log(small.toPrecision(2)); // "0.00012"toExponential() — Scientific Notation
let n = 1234567;
console.log(n.toExponential()); // "1.234567e+6"
console.log(n.toExponential(2)); // "1.23e+6"
console.log(n.toExponential(4)); // "1.2346e+6"Number Formatting
toLocaleString() — Human-Readable Format
let amount = 1234567.89;
// Indian format (lakhs/crores)
console.log(amount.toLocaleString("en-IN"));
// "12,34,567.89"
// US format
console.log(amount.toLocaleString("en-US"));
// "1,234,567.89"
// Currency format — Indian Rupee
console.log(amount.toLocaleString("en-IN", {
style: "currency",
currency: "INR",
}));
// "₹12,34,567.89"
// Currency format — US Dollar
console.log(amount.toLocaleString("en-US", {
style: "currency",
currency: "USD",
}));
// "$1,234,567.89"
// Percentage
console.log((0.1875).toLocaleString("en-IN", {
style: "percent",
minimumFractionDigits: 1,
}));
// "18.8%"Custom Currency Formatter
function formatCurrency(amount, currency = "INR", locale = "en-IN") {
return amount.toLocaleString(locale, {
style: "currency",
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
}
console.log(formatCurrency(55000)); // ₹55,000.00
console.log(formatCurrency(1234567.5)); // ₹12,34,567.50
console.log(formatCurrency(99.9, "USD", "en-US")); // $99.90Safe Number Operations
Check Before Using
function safeParseInt(value, fallback = 0) {
let parsed = parseInt(value, 10);
return Number.isNaN(parsed) ? fallback : parsed;
}
function safeParseFloat(value, fallback = 0) {
let parsed = parseFloat(value);
return Number.isNaN(parsed) ? fallback : parsed;
}
console.log(safeParseInt("42")); // 42
console.log(safeParseInt("abc")); // 0 (fallback)
console.log(safeParseInt("abc", -1)); // -1 (custom fallback)
console.log(safeParseFloat("3.14")); // 3.14
console.log(safeParseFloat("abc")); // 0 (fallback)Check if a String is a Valid Number
function isNumeric(value) {
return !Number.isNaN(parseFloat(value)) && isFinite(value);
}
console.log(isNumeric("42")); // true
console.log(isNumeric("3.14")); // true
console.log(isNumeric("-7")); // true
console.log(isNumeric("42px")); // false
console.log(isNumeric("abc")); // false
console.log(isNumeric("")); // false
console.log(isNumeric(Infinity)); // falseReal-World Examples
Example 1: Invoice Calculator
function createInvoice(items, taxRate = 18, discountPercent = 0) {
let subtotal = items.reduce((sum, { price, qty }) => sum + price * qty, 0);
let discount = parseFloat((subtotal * discountPercent / 100).toFixed(2));
let taxable = parseFloat((subtotal - discount).toFixed(2));
let tax = parseFloat((taxable * taxRate / 100).toFixed(2));
let total = parseFloat((taxable + tax).toFixed(2));
return { subtotal, discount, taxable, tax, total };
}
let invoice = createInvoice([
{ name: "JavaScript Course", price: 1999, qty: 1 },
{ name: "React Course", price: 2499, qty: 1 },
{ name: "Node.js Course", price: 1799, qty: 1 },
], 18, 10);
console.log("=== 🧾 Invoice ===");
console.log(`Subtotal : ${formatCurrency(invoice.subtotal)}`);
console.log(`Discount : -${formatCurrency(invoice.discount)}`);
console.log(`Taxable : ${formatCurrency(invoice.taxable)}`);
console.log(`GST 18% : ${formatCurrency(invoice.tax)}`);
console.log(`TOTAL : ${formatCurrency(invoice.total)}`);
function formatCurrency(n) {
return n.toLocaleString("en-IN", { style: "currency", currency: "INR" });
}
// Output:
// Subtotal : ₹6,297.00
// Discount : -₹629.70
// Taxable : ₹5,667.30
// GST 18% : ₹1,020.11
// TOTAL : ₹6,687.41Example 2: Form Input Validator
function validateNumberInput(value, { min, max, integer = false, label = "Value" } = {}) {
let errors = [];
// Check if it's a number at all
if (value === "" || value === null || value === undefined) {
return { valid: false, errors: [`${label} is required`] };
}
let num = Number(value);
if (Number.isNaN(num)) {
return { valid: false, errors: [`${label} must be a valid number`] };
}
if (!Number.isFinite(num)) {
errors.push(`${label} must be a finite number`);
}
if (integer && !Number.isInteger(num)) {
errors.push(`${label} must be a whole number`);
}
if (min !== undefined && num < min) {
errors.push(`${label} must be at least ${min}`);
}
if (max !== undefined && num > max) {
errors.push(`${label} must be at most ${max}`);
}
return { valid: errors.length === 0, value: num, errors };
}
let tests = [
["25", { min: 18, max: 65, integer: true, label: "Age" }],
["15", { min: 18, max: 65, integer: true, label: "Age" }],
["3.14", { min: 0, max: 10, integer: false, label: "Rating" }],
["abc", { min: 0, max: 10, label: "Score" }],
["", { label: "Quantity" }],
["99999", { min: 0, max: 1000, label: "Price" }],
];
tests.forEach(([val, opts]) => {
let result = validateNumberInput(val, opts);
console.log(result.valid
? `✅ "${val}" → ${opts.label}: ${result.value}`
: `❌ "${val}" → ${result.errors.join(", ")}`
);
});
// Output:
// ✅ "25" → Age: 25
// ❌ "15" → Age must be at least 18
// ✅ "3.14" → Rating: 3.14
// ❌ "abc" → Score must be a valid number
// ❌ "" → Quantity is required
// ❌ "99999" → Price must be at most 1000Example 3: Score Board with Formatting
let players = [
{ name: "Mihir", score: 9823.5, wins: 42 },
{ name: "Priya", score: 11204.0, wins: 58 },
{ name: "Rahul", score: 7654.25, wins: 31 },
{ name: "Sara", score: 15000.8, wins: 71 },
{ name: "Arjun", score: 8901.1, wins: 45 },
];
let sorted = [...players].sort((a, b) => b.score - a.score);
let total = players.reduce((s, p) => s + p.score, 0);
let avg = total / players.length;
console.log("=== 🏆 Leaderboard ===");
sorted.forEach(({ name, score, wins }, i) => {
let pct = ((score / total) * 100).toFixed(1);
console.log(
`${i + 1}. ${name.padEnd(8)} ` +
`Score: ${score.toLocaleString("en-IN", { minimumFractionDigits: 1 }).padStart(10)} ` +
`Wins: ${String(wins).padStart(3)} ` +
`Share: ${pct}%`
);
});
console.log(`\nAverage Score : ${avg.toLocaleString("en-IN", { maximumFractionDigits: 1 })}`);
console.log(`Total Score : ${total.toLocaleString("en-IN")}`);
// Output:
// 1. Sara Score: 15,000.8 Wins: 71 Share: 28.8%
// 2. Priya Score: 11,204.0 Wins: 58 Share: 21.5%
// 3. Mihir Score: 9,823.5 Wins: 42 Share: 18.8%
// 4. Arjun Score: 8,901.1 Wins: 45 Share: 17.1%
// 5. Rahul Score: 7,654.2 Wins: 31 Share: 14.7%Example 4: Unit Converter
const conversions = {
length: {
kmToMiles: n => parseFloat((n * 0.621371).toFixed(4)),
milesToKm: n => parseFloat((n * 1.60934).toFixed(4)),
mToFeet: n => parseFloat((n * 3.28084).toFixed(4)),
feetToM: n => parseFloat((n * 0.3048).toFixed(4)),
},
weight: {
kgToLbs: n => parseFloat((n * 2.20462).toFixed(4)),
lbsToKg: n => parseFloat((n * 0.453592).toFixed(4)),
gToOz: n => parseFloat((n * 0.035274).toFixed(4)),
},
temperature: {
cToF: c => parseFloat(((c * 9/5) + 32).toFixed(2)),
fToC: f => parseFloat(((f - 32) * 5/9).toFixed(2)),
cToK: c => parseFloat((c + 273.15).toFixed(2)),
},
};
console.log("=== 📏 Unit Converter ===");
console.log(`100 km = ${conversions.length.kmToMiles(100)} miles`);
console.log(`70 kg = ${conversions.weight.kgToLbs(70)} lbs`);
console.log(`100°C = ${conversions.temperature.cToF(100)}°F`);
console.log(`37°C = ${conversions.temperature.cToF(37)}°F (body temp)`);
console.log(`0°C = ${conversions.temperature.cToK(0)}K`);
// Output:
// 100 km = 62.1371 miles
// 70 kg = 154.3234 lbs
// 100°C = 212°F
// 37°C = 98.6°F (body temp)
// 0°C = 273.15KNumber Methods Cheat Sheet
| Method / Property | What it does | Example |
|---|---|---|
Number.isNaN(n) | Is it NaN? | Number.isNaN(NaN) → true |
Number.isFinite(n) | Is it finite? | Number.isFinite(Infinity) → false |
Number.isInteger(n) | Is it whole? | Number.isInteger(4.0) → true |
Number.isSafeInteger(n) | Safe for exact math? | Number.isSafeInteger(9e15) → false |
Number.parseInt(s) | String to int | Number.parseInt("42px") → 42 |
Number.parseFloat(s) | String to float | Number.parseFloat("3.14") → 3.14 |
n.toFixed(d) | Fixed decimals (string) | (3.14159).toFixed(2) → "3.14" |
n.toPrecision(d) | Sig digits (string) | (123.4).toPrecision(4) → "123.4" |
n.toString(base) | Number to string | (255).toString(16) → "ff" |
n.toExponential(d) | Scientific notation | (12345).toExponential(2) → "1.23e+4" |
n.toLocaleString() | Formatted string | (1234567).toLocaleString("en-IN") → "12,34,567" |
Number.MAX_SAFE_INTEGER | 9007199254740991 | Largest safe int |
Number.EPSILON | ~2.22e-16 | Smallest difference |
Number.MAX_VALUE | ~1.8e+308 | Largest finite number |
Number.POSITIVE_INFINITY | Infinity | |
Number.NaN | NaN value |
Common Mistakes
Mistake 1: Using Global isNaN() Instead of Number.isNaN()
// ❌ Global isNaN() converts the value first — misleading results!
console.log(isNaN("hello")); // true — "hello" gets coerced to NaN
console.log(isNaN(undefined)); // true — undefined gets coerced to NaN
console.log(isNaN("")); // false — "" gets coerced to 0!
// ✅ Number.isNaN() — no coercion, exact check
console.log(Number.isNaN("hello")); // false — it's a string, not NaN
console.log(Number.isNaN(undefined)); // false — it's undefined, not NaN
console.log(Number.isNaN(NaN)); // true ✅Mistake 2: toFixed() Returns a String
let price = 99.9;
// ❌ toFixed returns a STRING — arithmetic breaks!
let withTax = price.toFixed(2) + 10; // "99.90" + 10 = "99.9010" ❌ (string concat!)
// ✅ Convert back to number first
let withTax2 = parseFloat(price.toFixed(2)) + 10; // 109.9 ✅
let withTax3 = Number(price.toFixed(2)) + 10; // 109.9 ✅Mistake 3: Comparing with NaN Directly
let result = parseInt("abc");
// ❌ NaN is never equal to anything — even itself!
console.log(result === NaN); // false ❌
console.log(result == NaN); // false ❌
console.log(NaN === NaN); // false ❌
// ✅ Always use Number.isNaN() to check
console.log(Number.isNaN(result)); // true ✅Mistake 4: Floating Point in Conditionals
let total = 0.1 + 0.2;
// ❌ Will never be true due to floating point!
if (total === 0.3) {
console.log("Equal"); // Never runs ❌
}
// ✅ Use a tolerance (epsilon) comparison
if (Math.abs(total - 0.3) < Number.EPSILON) {
console.log("Equal ✅"); // Works! ✅
}
// ✅ Or round both sides before comparing
if (parseFloat(total.toFixed(2)) === 0.3) {
console.log("Equal ✅"); // Works! ✅
}Mistake 5: parseInt Without Radix
// ❌ No radix — behavior can be unexpected with leading zeros
console.log(parseInt("010")); // Could be 8 (octal) in older engines!
console.log(parseInt("0xff")); // 255 — automatically hexadecimal
// ✅ Always specify radix 10 for decimal numbers
console.log(parseInt("010", 10)); // 10 ✅
console.log(parseInt("42", 10)); // 42 ✅Practical Exercise
Create a file called number-object.js:
// 🎯 Number Object Practice
// 1. Number type detective
console.log("=== 🔍 Number Type Checks ===");
let values = [42, 3.14, NaN, Infinity, -Infinity, "42", null, undefined, 0, -0];
values.forEach(v => {
console.log(
`${String(v).padEnd(12)} | ` +
`isNaN: ${String(Number.isNaN(v)).padEnd(6)} | ` +
`isFinite: ${String(Number.isFinite(v)).padEnd(6)} | ` +
`isInteger: ${String(Number.isInteger(v)).padEnd(6)} | ` +
`isSafeInt: ${Number.isSafeInteger(v)}`
);
});
// 2. String-to-number parser
console.log("\n=== 🔄 Parsing Comparison ===");
let inputs = ["42", "3.14", " 100 ", "42px", "px42", "0xFF", "3.14.15", ""];
inputs.forEach(input => {
let pi = parseInt(input, 10);
let pf = parseFloat(input);
let n = Number(input);
console.log(
`"${input}".padEnd(12) → ` +
`parseInt: ${String(pi).padEnd(8)} ` +
`parseFloat: ${String(pf).padEnd(8)} ` +
`Number: ${n}`
);
});
// 3. Currency formatter
console.log("\n=== 💰 Currency Formatter ===");
let amounts = [1000, 12345.678, 9999999, 0.5, 100000000];
amounts.forEach(amount => {
let inr = amount.toLocaleString("en-IN", { style: "currency", currency: "INR", maximumFractionDigits: 2 });
let usd = amount.toLocaleString("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 2 });
console.log(`${String(amount).padEnd(14)} → INR: ${inr.padEnd(18)} USD: ${usd}`);
});
// 4. Safe math utility
console.log("\n=== 🛡️ Safe Math ===");
function safeDivide(a, b, fallback = 0) {
if (!Number.isFinite(a) || !Number.isFinite(b)) return fallback;
if (b === 0) return fallback;
return parseFloat((a / b).toFixed(10));
}
function safePercentage(part, total, decimals = 1) {
if (total === 0) return "N/A";
return parseFloat(((part / total) * 100).toFixed(decimals)) + "%";
}
console.log(`10 / 2 = ${safeDivide(10, 2)}`);
console.log(`10 / 0 = ${safeDivide(10, 0)}`);
console.log(`NaN / 5 = ${safeDivide(NaN, 5)}`);
console.log(`Inf / 2 = ${safeDivide(Infinity, 2)}`);
console.log(`45/200 = ${safePercentage(45, 200)}`);
console.log(`0/0 = ${safePercentage(0, 0)}`);
console.log(`1/3 = ${safePercentage(1, 3, 2)}`);Run it:
node number-object.jsExpected Output:
=== 🔍 Number Type Checks ===
42 | isNaN: false | isFinite: true | isInteger: true | isSafeInt: true
3.14 | isNaN: false | isFinite: true | isInteger: false | isSafeInt: false
NaN | isNaN: true | isFinite: false | isInteger: false | isSafeInt: false
Infinity | isNaN: false | isFinite: false | isInteger: false | isSafeInt: false
...
=== 💰 Currency Formatter ===
1000 → INR: ₹1,000.00 USD: $1,000.00
12345.678 → INR: ₹12,345.68 USD: $12,345.68
9999999 → INR: ₹99,99,999.00 USD: $9,999,999.00
...
=== 🛡️ Safe Math ===
10 / 2 = 5
10 / 0 = 0
NaN / 5 = 0
Inf / 2 = 0
45/200 = 22.5%
0/0 = N/A
1/3 = 33.33%Key Takeaways
Congratulations! 🎉 You now have a deep, complete understanding of numbers in JavaScript.
✅ All numbers are float64 — no separate int type. This causes the floating point issue (0.1 + 0.2 !== 0.3).
✅ Fix float issues — parseFloat(n.toFixed(2)), work in integers (paise/cents), or use Number.EPSILON.
✅ NaN — results from invalid math. Use Number.isNaN() — never === NaN or global isNaN().
✅ Parsing:
parseInt(str, 10)— string to integer, ignores trailing charsparseFloat(str)— string to decimalNumber(val)— strict, returns NaN for mixed strings
✅ Formatting:
toFixed(d)→ fixed decimals as stringtoPrecision(d)→ significant digits as stringtoLocaleString(locale, opts)→ human-readable with currency/percent support
✅ Checks:
Number.isNaN()— is it NaN?Number.isFinite()— is it finite?Number.isInteger()— is it whole?Number.isSafeInteger()— can it be represented exactly?
✅ Always specify radix 10 when using parseInt().
Best Practices
- ✅ Always use
Number.isNaN()— never globalisNaN()or=== NaN - ✅ Always pass radix 10 to
parseInt()—parseInt(val, 10) - ✅ Remember
toFixed()returns a string — wrap inparseFloat()if you need a number - ✅ Use
toLocaleString()for all user-facing number and currency display - ✅ Fix floating-point comparisons with
Number.EPSILONor by rounding both sides - ✅ For financial calculations, work in smallest units (paise/cents) to avoid float issues
- ✅ Use
Number.isFinite()to guard againstInfinityandNaNbefore doing math - ✅ Build
safeParseIntandsafeParseFloatutilities in your projects — use them everywhere
What's Next?
Great work! 🎉 You now understand numbers in JavaScript at a deep level.
Next up, the final topic in the JavaScript Objects section:
Boolean → — truthy and falsy values, logical operators, type coercion, and everything about booleans in JavaScript!
Let's finish strong! 💪