Complete JavaScript Course Module 2: Beginner: Variables and Data Types

JavaScript Number Methods: toFixed, toLocaleString and Intl.NumberFormat

  • Beginner
  • Lesson 2.6
  • 6 min read
  • 9 of 76 in the course

In short

JavaScript number methods help you round, check and format numbers. Learn toFixed, toPrecision, Number.isInteger, BigInt, and how to format currency with Intl.NumberFormat.

JavaScript number methods help you round, check and format numbers. Learn toFixed, toPrecision, Number.isInteger, BigInt, and how to format currency with Intl.NumberFormat.

Number methods for turning numbers into strings

Every number in JavaScript comes with built-in methods: small functions you call with a dot, like price.toFixed(2). You met toFixed briefly in the Numbers and Math lesson. Here are the main methods that turn a number into a string:

MethodWhat it doesExampleResult
toString()Number to string(42).toString()"42"
toString(base)Number in another base(255).toString(16)"ff"
toFixed(digits)Fixed number of decimals(3.14159).toFixed(2)"3.14"
toPrecision(digits)Fixed number of significant digits(123.456).toPrecision(4)"123.5"
toLocaleString()Formatted for a language and region(1234.5).toLocaleString("en-US")"1,234.5"

All of them return a string, not a number. That is perfect for showing values on a page, but you should do your maths before you format.

const price = 19.999;

console.log(price.toFixed(2));        // Output: 20.00
console.log(price.toFixed(0));        // Output: 20
console.log((5).toFixed(2));          // Output: 5.00

console.log((123.456).toPrecision(2)); // Output: 1.2e+2
console.log((0.000123).toPrecision(2)); // Output: 0.00012

console.log((5).toString(2));         // Output: 101   (binary)
console.log((255).toString(16));      // Output: ff    (hexadecimal, used in CSS colours)

console.log(typeof price.toFixed(2)); // Output: string

toFixed counts digits after the decimal point. toPrecision counts significant digits (all the meaningful digits from the first non-zero one), and may switch to scientific notation like 1.2e+2, which means 1.2 × 10². The brackets around (5) are needed because 5.toFixed() would confuse JavaScript: it would think the dot is a decimal point.

Common mistake: Adding formatted values. price.toFixed(2) + 1 gives "20.001", because toFixed returned a string and + joins text. Calculate with numbers first, format at the very end.

Checking numbers: Number.isInteger, Number.isNaN and Number.isFinite

The Number object also has static methods, which you call on Number itself rather than on a value. They answer yes/no questions about a value:

MethodReturns true whenExample
Number.isInteger(x)x is a whole numberNumber.isInteger(4.0) is true
Number.isNaN(x)x is exactly NaNNumber.isNaN(NaN) is true
Number.isFinite(x)x is a real number, not Infinity or NaNNumber.isFinite(10 / 0) is false
Number.isSafeInteger(x)x is a whole number in the safe rangeNumber.isSafeInteger(2 ** 53) is false

Older global versions, isNaN() and isFinite(), also exist, but they convert the value to a number first, which causes surprises. The Number. versions never convert:

console.log(isNaN("hello"));         // Output: true   (converted "hello" to NaN first)
console.log(Number.isNaN("hello"));  // Output: false  (it's a string, not NaN)

console.log(isFinite("42"));         // Output: true
console.log(Number.isFinite("42"));  // Output: false  (a string is not a number)

// Checking a quantity typed into a form
const input = "3";
const quantity = Number(input);

if (Number.isInteger(quantity) && quantity > 0) {
  console.log(`Adding ${quantity} items`);
} else {
  console.log("Please enter a whole number above 0");
}
// Output: Adding 3 items

With "2.5" or "abc" in input, you would see the error message instead.

Number.MAX_SAFE_INTEGER and BigInt for very large numbers

Normal JavaScript numbers can store whole numbers exactly only up to Number.MAX_SAFE_INTEGER, which is 9007199254740991 (about 9 quadrillion). Above that, numbers lose precision and maths goes quietly wrong:

console.log(Number.MAX_SAFE_INTEGER);              // Output: 9007199254740991
console.log(9007199254740992 === 9007199254740993); // Output: true  (!)
console.log(Number.MAX_SAFE_INTEGER + 2);          // Output: 9007199254740992

For bigger whole numbers, use BigInt, a separate number type for whole numbers of any size. Create one by adding n to the end of a number, or with BigInt():

const big = 9007199254740993n;
console.log(big + 2n);                 // Output: 9007199254740995n
console.log(typeof big);               // Output: bigint

const fromText = BigInt("123456789012345678901234567890");
console.log(fromText * 2n);            // Output: 246913578024691357802469135780n

console.log(7n / 2n);                  // Output: 3n   (decimals are cut off)
console.log(10n === 10);               // Output: false (different types)
console.log(10n == 10);                // Output: true

// console.log(10n + 5);               // TypeError: Cannot mix BigInt and other types
console.log(10n + BigInt(5));          // Output: 15n
console.log(Number(10n) + 5);          // Output: 15

The rules for BigInt are simple but strict:

  • BigInts hold only whole numbers. Division drops the decimal part.
  • You cannot mix BigInt and normal numbers in maths; convert one side with BigInt() or Number().
  • Math methods like Math.round do not accept BigInts.
  • JSON.stringify throws an error on BigInts, so convert them to strings before sending them to a server.

You will need BigInt for things like very large IDs from databases, or precise maths on huge whole numbers. For prices and everyday counting, normal numbers are the right choice.

Formatting currency, percent and compact numbers with Intl.NumberFormat

People in different countries write numbers differently. In the US one thousand and a half is 1,000.5; in Germany it is 1.000,5. Intl.NumberFormat is the browser's built-in formatter that knows these rules. You give it a locale (a language and region code like "en-US") and options, and it creates a reusable formatter.

const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
const eur = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" });
const inr = new Intl.NumberFormat("en-IN", { style: "currency", currency: "INR" });

console.log(usd.format(1234.5));    // Output: $1,234.50
console.log(eur.format(1234.5));    // Output: 1.234,50 €
console.log(inr.format(123456));    // Output: ₹1,23,456.00

The formatter adds the currency symbol, the right separators and the right number of decimals for that currency. The currency option uses three-letter codes like "USD", "EUR" or "GBP".

The style option has other useful values too:

const percent = new Intl.NumberFormat("en-US", { style: "percent", maximumFractionDigits: 1 });
console.log(percent.format(0.256));   // Output: 25.6%

const compact = new Intl.NumberFormat("en-US", { notation: "compact" });
console.log(compact.format(15300));   // Output: 15K
console.log(compact.format(2500000)); // Output: 2.5M

const longCompact = new Intl.NumberFormat("en-US", { notation: "compact", compactDisplay: "long" });
console.log(longCompact.format(1234567)); // Output: 1.2 million

const speed = new Intl.NumberFormat("en-US", { style: "unit", unit: "kilometer-per-hour" });
console.log(speed.format(50));        // Output: 50 km/h

Notice that "percent" expects a fraction: 0.256 becomes 25.6%. Compact notation is great for follower counts and view numbers on social media style pages.

OptionExample valuesWhat it controls
style"decimal", "currency", "percent", "unit"The kind of number
currency"USD", "EUR", "JPY"Which currency (needed for "currency")
minimumFractionDigits / maximumFractionDigits0 to 20How many decimals
notation"standard", "compact", "scientific"Short forms like 15K
unit"kilogram", "liter", "percent"The unit (needed for "unit")

Quick formatting with toLocaleString

If you only need to format one number, toLocaleString() takes the same locale and options directly, without creating a formatter first:

const visitors = 1234567.891;

console.log(visitors.toLocaleString("en-US"));  // Output: 1,234,567.891
console.log(visitors.toLocaleString("de-DE"));  // Output: 1.234.567,891
console.log(visitors.toLocaleString("en-US", { maximumFractionDigits: 0 })); // Output: 1,234,568

const price = 49.9;
console.log(price.toLocaleString("en-GB", { style: "currency", currency: "GBP" })); // Output: £49.90

console.log(visitors.toLocaleString());  // Output: depends on the visitor's own settings

If you leave out the locale, the browser uses the visitor's own language settings, which is often exactly what you want.

Tip: When you format many numbers the same way, such as every price in a product list, create one Intl.NumberFormat and reuse its format method. It is faster than calling toLocaleString with options each time.

Practice exercise

Make a small sales summary. Start with const sales = [1299.5, 349.99, 89, 2450];. Use reduce (or a loop) to get the total, then log it as US dollars and as euros in German format. Also log the average with toFixed(2), and log the total in compact form, like 4.2K.

Hint: create two currency formatters and one with notation: "compact". Do all the adding and dividing with plain numbers before you call format.

Key takeaways

  • toFixed, toPrecision, toString and toLocaleString all return strings, so format at the end.
  • Use Number.isInteger, Number.isNaN and Number.isFinite; they never convert the value first.
  • Whole numbers are exact only up to Number.MAX_SAFE_INTEGER; use BigInt (123n) beyond that, and never mix it with normal numbers.
  • Intl.NumberFormat formats currency, percentages, units and compact numbers for any locale.