DEV Community

Cover image for JavaScript Number Formatting — The Complete Guide for Beginners
FSCSS
FSCSS

Posted on • Originally published at i.devtem.org

JavaScript Number Formatting — The Complete Guide for Beginners

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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%"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Currency

const usd = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
});
console.log(usd.format(9.5));
// "$9.50"
Enter fullscreen mode Exit fullscreen mode

Percentage

const pct = new Intl.NumberFormat("en-US", {
  style: "percent",
  minimumFractionDigits: 1,
});
console.log(pct.format(0.756));
// "75.6%"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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));
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)