Learn every JavaScript number formatting method you actually need — toFixed, toPrecision, toLocaleString, Intl.NumberFormat, Math utilities and the traps to avoid.
Numbers are everywhere in web apps — prices, scores, statistics, percentages, progress bars. But JavaScript stores all numbers as 64-bit floating point values, and raw floating point results look terrible to users.
This is what I mean:
console.log(0.1 + 0.2);
// 0.30000000000000004
That is not a bug. That is how binary floating point math works. The fix is not to change how JavaScript stores numbers — it is to control how you display them. That is what number formatting is.
By the end of this article you will know every method you need, when to use each one, and the traps that trip up beginners.
What Is Number Formatting?
Number formatting is the process of converting a raw numeric value into a string that is readable, consistent, and appropriate for your audience.
Raw value vs formatted output:
| Raw Value | Formatted Output | Context |
|---|---|---|
1234567.8 |
1,234,567.80 |
E-commerce price |
0.875 |
87.5% |
Progress indicator |
1500000 |
1.5M |
Social media count |
255 |
#ff |
Hex colour code |
3.14159265 |
3.14 |
Display result |
Formatting is purely cosmetic — the underlying number never changes. You are just deciding how it looks.
1. toFixed() — Controlling Decimal Places
toFixed(n) rounds a number to n decimal places and returns a string.
let price = 9.999;
console.log(price.toFixed(2));
// "10.00"
let score = 3.14159;
console.log(score.toFixed(3));
// "3.142"
let whole = 7;
console.log(whole.toFixed(2));
// "7.00"
Real-world uses
// Currency
let total = 24.5;
console.log("$" + total.toFixed(2));
// "$24.50"
// Percentage
let progress = 0.876;
console.log((progress * 100).toFixed(1) + "%");
// "87.6%"
The trap beginners hit
toFixed() returns a string, not a number. If you try to add to it, JavaScript will concatenate instead of add:
// Wrong
let x = (1.5).toFixed(2) + 1;
console.log(x);
// "1.501" ← string concatenation!
// Right
let x = Number((1.5).toFixed(2)) + 1;
console.log(x);
// 2.5 ← actual addition
Always wrap in Number() if you need to do more math after formatting.
2. toPrecision() — Significant Figures
toPrecision(n) formats a number to n total significant digits — counting both sides of the decimal point. Also returns a string.
let n = 123.456;
console.log(n.toPrecision(5));
// "123.46"
let small = 0.00123;
console.log(small.toPrecision(2));
// "0.0012"
let big = 9876543;
console.log(big.toPrecision(4));
// "9877000"
toFixed vs toPrecision — what is the difference?
let n = 3.14159;
console.log(n.toFixed(2)); // "3.14" → 2 decimal places
console.log(n.toPrecision(4)); // "3.142" → 4 total digits
Use toFixed() for currency, scores, and everyday decimals.
Use toPrecision() for scientific or measurement data where total precision matters more than decimal places.
3. toString() — Base Conversion
toString(radix) converts a number to a string. Pass a base (radix) to convert to binary, octal, hexadecimal, and more.
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" — hex
Practical use — generating hex colours
function toHex(r, g, b) {
return "#" +
r.toString(16).padStart(2, "0") +
g.toString(16).padStart(2, "0") +
b.toString(16).padStart(2, "0");
}
console.log(toHex(255, 165, 0));
// "#ffa500"
4. toLocaleString() — Human-Friendly Numbers
toLocaleString() formats a number according to language and regional settings. It automatically adds commas, the right decimal separator, and currency symbols — no manual string splitting needed.
let big = 1234567.89;
// Automatic locale (user's browser settings)
console.log(big.toLocaleString());
// "1,234,567.89" (in US locale)
// Explicit locale
console.log(big.toLocaleString("de-DE"));
// "1.234.567,89" (German — note the period/comma swap)
// Naira currency
console.log(big.toLocaleString("en-NG", {
style: "currency",
currency: "NGN"
}));
// "₦1,234,567.89"
This is the easiest way to add commas to large numbers for display.
5. Intl.NumberFormat — The Production-Grade Way
Intl.NumberFormat is the full standards-based API for number formatting. It is more powerful than toLocaleString() and significantly faster when you are formatting the same style repeatedly (because you create the formatter once and reuse it).
Basic usage
const fmt = new Intl.NumberFormat("en-US");
console.log(fmt.format(1234567));
// "1,234,567"
Currency
const usd = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
});
console.log(usd.format(9.5));
// "$9.50"
Percentage
const pct = new Intl.NumberFormat("en-US", {
style: "percent",
minimumFractionDigits: 1,
});
console.log(pct.format(0.756));
// "75.6%"
Compact notation — dashboard and social style
const compact = new Intl.NumberFormat("en-US", {
notation: "compact",
});
console.log(compact.format(1500000)); // "1.5M"
console.log(compact.format(48000)); // "48K"
console.log(compact.format(999)); // "999"
Controlling digit lengths
const precise = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 4,
});
console.log(precise.format(1.5)); // "1.50"
console.log(precise.format(1.56789)); // "1.5679"
Intl.NumberFormat is supported in all modern browsers and Node.js. Use it for any production app.
6. Math Utilities — Rounding Before You Format
Before formatting, you often need to round a number first. These are the key Math methods:
Math.round(4.6) // 5 — nearest integer
Math.round(4.4) // 4
Math.floor(4.9) // 4 — always rounds DOWN
Math.floor(-4.1) // -5
Math.ceil(4.1) // 5 — always rounds UP
Math.ceil(-4.9) // -4
Math.trunc(4.9) // 4 — removes decimals, no rounding
Math.trunc(-4.9) // -4 — note: not the same as floor for negatives
Math.abs(-42) // 42 — removes the minus sign
Math.max(1, 9, 3) // 9
Math.min(1, 9, 3) // 1
Math.pow(2, 8) // 256
Rounding to N decimal places reliably
toFixed(2) can have precision issues in edge cases. For actual math (not just display), this is more reliable:
// Round to 2 decimal places
function round2(n) {
return Math.round(n * 100) / 100;
}
console.log(round2(1.005)); // 1.01
console.log(round2(2.675)); // 2.68
7. Common Mistakes to Avoid
Mistake 1 — Floating point comparison
// Wrong
console.log(0.1 + 0.2 === 0.3);
// false
// Right — use a tolerance
console.log(Math.abs(0.1 + 0.2 - 0.3) < 0.0001);
// true
Never compare floating point numbers with ===. Always use a small tolerance.
Mistake 2 — Not guarding against NaN
// Wrong
let x = parseInt("hello");
console.log(x.toFixed(2));
// NaN — and can crash your UI
// Right
let val = parseInt("hello");
if (!isNaN(val)) {
console.log(val.toFixed(2));
}
Always check isNaN() before calling formatting methods on values that came from user input or external data.
Mistake 3 — Parsing a formatted string
// Wrong — this breaks
let price = "$1,234.50";
let num = parseFloat(price);
console.log(num);
// NaN
// Right — strip formatting first
let clean = price.replace(/[^0-9.]/g, "");
let num = parseFloat(clean);
console.log(num);
// 1234.5
If you need to parse a number back out of a formatted string, strip the non-numeric characters first.
Quick Reference
| Method | Returns | Best for |
|---|---|---|
toFixed(n) |
string | Prices, decimals |
toPrecision(n) |
string | Scientific data |
toString(radix) |
string | Base conversion, hex |
toLocaleString() |
string | Commas, quick locale |
Intl.NumberFormat |
formatter object | Production apps |
Math.round() |
number | Nearest integer |
Math.floor() |
number | Round down |
Math.ceil() |
number | Round up |
Math.trunc() |
number | Drop decimals |
Get the PDF Guide
This article is also available as a clean 8-page PDF with a full cheatsheet page — useful to keep open while you code.
Download the JavaScript Number Formatting PDF Guide
Covers everything in this article plus a printable cheatsheet with every method, example, and output on one page.
Top comments (0)