Number Toolbox 0/7

JavaScript basicsNumbers in plain wordsOne tool at a time

Number
Toolbox

JavaScript has one main number type for whole numbers and decimals alike. This guide shows how to check numbers, turn text into numbers, round them, do maths, avoid decimal surprises and show them nicely as money, with a small example for each that you can run.

JavaScript ES202421 tools
00

Key terms in plain words

Never written code before? Start here. Every word below shows up later on this page, and each one comes with an everyday comparison. Underlined words in the modules link back to these cards.

25 terms in 5 groups. Hover an underlined word anywhere on the page for a quick reminder, or click it to jump here.

What a number is

Think of JavaScript as a shop counter with a till. Numbers are the amounts that go through it, and a few odd slips can come out of it too.

Number
JavaScript has one kind of number for everything, whether it has a decimal point or not. Prices, counts and percentages all use it.
For example 450 and 7.5 are both numbers.
Type
The kind of value something is, such as a number or a piece of text. typeof tells you the type, and it matters because the same symbol can behave differently on different types.
For example typeof 7.5 gives "number".
Whole number (integer)
A number with nothing after the decimal point, such as 5, 0 or -12. Programmers call it an integer. Number.isInteger checks for one.
Decimal
A number with a part after the decimal point, such as 4.5 or 0.25. Decimals are where rounding and tiny storage errors come in.
NaN
Short for "not a number". It is what you get from maths that makes no sense, such as multiplying a word. Oddly, NaN is never equal to anything, even itself, so check for it with Number.isNaN.
For example "abc" * 2 gives NaN.
Infinity
A special value bigger than every other number. You get it by dividing by zero or going past the largest number JavaScript can hold. There is a minus version too.
For example 10 / 0 gives Infinity.

Turning text into numbers

What a customer types into a form arrives as text, even when it looks like an amount. You have to turn it into a number first.

String
Programmers call text a string. A form field always gives you a string, even "42", and adding strings joins them instead of summing them, so "7" + 1 gives "71".
Converting
Turning a value of one type into another, here text into a number. Number(text) converts the whole thing and gives NaN if any of it is junk.
For example Number("42") gives 42.
parseInt and parseFloat
They read a number from the start of some text and stop at the first character that isn't part of it, so "42px" gives 42. parseInt reads whole numbers and parseFloat reads decimals. Always give parseInt a 10, so it counts in ordinary tens.
For example parseInt("42px", 10) gives 42.
True or false
The answer from a check is one of two values: true or false. Programmers call this a boolean. Every is... check on this page gives one.

Rounding and everyday maths

The sums a shop does all day: rounding totals, splitting change and picking a lucky number.

Rounding
Turning a decimal into a nearby whole number, or into fewer decimal places. Math.round goes to the nearest one, and toFixed rounds to a set number of decimals but hands back text.
For example Math.round(4.567) gives 5.
floor, ceil and trunc
Math.floor always goes down, Math.ceil always goes up, and Math.trunc simply cuts the decimals off. They only disagree with negative numbers, where down means further from zero.
For example Math.floor(-4.5) is -5, Math.trunc(-4.5) is -4.
Math
A built-in set of maths tools that every JavaScript program has. You use them by writing Math. and the tool's name, such as Math.max for the biggest of some numbers.
Remainder (%)
What is left after dividing as many whole times as you can. 17 % 5 is 2. If a number divided by 2 leaves 0, it is even.
Power and square root
A power multiplies a number by itself several times: 2 ** 10 is 2 times itself ten times, 1024. A square root goes the other way: the square root of 81 is 9, because 9 times 9 is 81.
Random number
Math.random() gives an unpredictable decimal from 0 up to just below 1. Stretch it, round it down and shift it to get a whole number in any range, such as a dice roll.
Array and spread
An array is a list of values in square brackets. Three dots in front of it, called spread, pour the items out separately, which is how you pass a whole list to a tool like Math.max.
For example Math.max(...[40, 75, 12]) gives 75.

Keeping money exact

Why a till that works in decimals can be off by a fraction, and how to stop that from costing anyone a paisa.

Binary
Computers store every number as a string of 1s and 0s. Some simple decimals, such as 0.1, can't be written exactly that way, just as 1/3 never ends when written as a decimal.
Floating point error
The tiny mistake left over when a decimal can't be stored exactly. It is why 0.1 + 0.2 shows 0.30000000000000004. Compare decimals by checking the gap is smaller than Number.EPSILON rather than using ===.
Smallest unit (paise)
Store money as whole paise (or cents) instead of rupees with decimals. Whole numbers add up exactly, so nothing goes missing. Divide by 100 only when you show the amount.
For example ₹4.50 is stored as 450 paise.
BigInt
Ordinary numbers stay exact only up to about 9 quadrillion. Past that, digits quietly go wrong. A BigInt is a separate kind of whole number, written with an n on the end, that stays exact at any size.
For example 9007199254740993n + 1n gives 9007199254740994n.

Showing numbers to people

Printing amounts on the receipt the way a customer in that country expects to read them.

Locale
A short code for a language and region, such as en-IN for English in India or en-US for the United States. It decides where commas go and how currency is written.
Thousands separator
Commas or spaces that split a long number into groups. India groups by lakhs and crores (12,34,567), while the US groups in threes (1,234,567).
Formatter (Intl.NumberFormat)
A reusable tool that turns numbers into display text: currency, percent or short forms like 2.4M. Build it once with your locale and options, then call its format as often as you like.
For example ₹12,34,567.89 comes from an en-IN currency formatter.
Currency
The money a number stands for. A formatter set to a currency adds the right symbol and the usual two decimal places for you.
01

Make and check

Write numbers, meet the special values NaN and Infinity, and test what kind of number you have.

Start hereNaNInfinityisIntegerMust know

In JavaScript, 7 and 7.5 are the same type: number. There are also a few special values. Infinity is what you get past the biggest number, and NaN, short for "not a number", is the answer to maths that makes no sense.

make.jsJAVASCRIPT
const price = 450;
const rate = 7.5;
const big = 1_000_000;          // underscores only help you read it
const tiny = 2.5e-3;            // 0.0025 in science notation

console.log(typeof price, typeof rate);  // whole or decimal, both are "number"
console.log(big, tiny);
console.log(10 / 0, -10 / 0);            // dividing by zero gives Infinity
console.log(0 / 0, "abc" * 2);           // NaN means "not a number"

Easy way to remember: NaN is still of type number. It just means the maths went wrong somewhere earlier.

Terminal OUTPUT
$ node make.js
number number
1000000 0.0025
Infinity -Infinity
NaN NaN
Number.isInteger(n)

Checks for a whole number with no decimals.

See the example
Gives true or falseOnly reads
Number.isFinite(n)

Checks for a real, countable number. Not NaN, not Infinity.

See the example
Gives true or falseOnly reads
Number.isNaN(n)

Checks for NaN without converting first.

See the example
Gives true or falseOnly reads
isNaN(x)

The older check. It converts text first, so "hello" counts.

See the example
Gives true or falseOnly reads
check.jsJAVASCRIPT
console.log(Number.isInteger(5), Number.isInteger(5.5));
console.log(Number.isFinite(42), Number.isFinite(Infinity));

// NaN is the only value that is not equal to itself
console.log(NaN === NaN);
console.log(Number.isNaN(NaN));        // the reliable check
console.log(isNaN("hello"));           // older isNaN converts first: true
console.log(Number.isNaN("hello"));    // Number.isNaN does not: false

Why it matters: NaN is never equal to anything, not even itself, so x === NaN is always false. Use Number.isNaN(x).

Terminal OUTPUT
$ node check.js
true false
true false
false
true
true
false
02

Text to number

Turn what a person typed into a real number, and catch it when they typed something else.

ConvertingNumberparseIntparseFloat
InputNumber(x)parseInt(x, 10)parseFloat(x)
"42"424242
"4.5"4.544.5
"42px"NaN4242
""0NaNNaN
"abc"NaNNaNNaN
Number(x)

Converts the whole value. Any junk gives NaN.

See the example
Gives a number or NaNMakes a new one
parseInt(text, base)

Reads a whole number from the start, stopping at junk. Always pass 10.

See the example
Gives a number or NaNMakes a new one
parseFloat(text)

Reads a decimal number from the start.

See the example
Gives a number or NaNMakes a new one
+x

A short way to write Number(x).

See the example
Gives a number or NaNMakes a new one
parse.jsJAVASCRIPT
console.log(Number("42"), Number("4.5"), Number(""));  // empty text becomes 0
console.log(Number("42px"));                  // any junk gives NaN

console.log(parseInt("42px", 10));            // reads digits until it hits junk
console.log(parseInt("08", 10), parseInt("ff", 16)); // always pass the base
console.log(parseFloat("3.14 metres"));
console.log(+"7" + 1, "7" + 1);               // + in front converts; + between joins text

const qty = Number("abc");
console.log(Number.isNaN(qty) ? "please enter a number" : qty);

Rule of thumb: use Number for form fields, since it rejects junk. Use parseInt or parseFloat only when you expect units like "px" on the end.

Terminal OUTPUT
$ node parse.js
42 4.5 0
NaN
42
8 255
3.14
8 71
please enter a number
03

Round it

Round up, round down, cut off decimals, or show a fixed number of decimal places.

RoundingMath.roundtoFixed
Valueroundfloorceiltrunc
4.5675454
4.55454
-4.5-4-5-4-4
Math.round(n)

To the nearest whole number. Halves go up.

See the example
Gives a numberMakes a new one
Math.floor(n)

Always down, towards minus infinity.

See the example
Gives a numberMakes a new one
Math.ceil(n)

Always up.

See the example
Gives a numberMakes a new one
Math.trunc(n)

Just cuts the decimals off.

See the example
Gives a numberMakes a new one
toFixed(digits)

Rounds to that many decimals for display.

See the example
Gives a stringMakes a new one
round.jsJAVASCRIPT
const n = 4.567;

console.log(Math.round(n), Math.floor(n), Math.ceil(n), Math.trunc(n));
console.log(Math.floor(-4.5), Math.trunc(-4.5));   // floor goes down, trunc cuts off

console.log(n.toFixed(2));           // "4.57": a string with 2 decimals
console.log(n.toFixed(0), typeof n.toFixed(2));
console.log(Number(n.toFixed(1)));   // back to a number

console.log((1234.5678).toPrecision(3)); // 3 significant digits

Watch for this: toFixed gives you text, not a number. Wrap it in Number() if you need to keep calculating.

Terminal OUTPUT
$ node round.js
5 4 5 4
-5 -4
4.57
5 string
4.6
1.23e+3
04

Math toolbox

Find the biggest and smallest, powers and roots, remainders and random numbers.

MathsMath.max%Math.random
Math.max / Math.min(...nums)

Picks the biggest or smallest. Spread an array into it.

See the example
Gives a numberOnly reads
Math.abs(n)

Removes the minus sign.

See the example
Gives a numberMakes a new one
a ** b

a to the power of b.

See the example
Gives a numberMakes a new one
Math.sqrt(n)

The square root.

See the example
Gives a numberMakes a new one
a % b

The remainder after dividing. Great for even or odd checks.

See the example
Gives a numberMakes a new one
Math.random()

A random decimal from 0 up to, not including, 1.

See the example
Gives a numberMakes a new one
math.jsJAVASCRIPT
console.log(Math.max(3, 9, 1), Math.min(3, 9, 1));
console.log(Math.max(...[40, 75, 12]));      // spread an array in
console.log(Math.abs(-8), 2 ** 10, Math.sqrt(81));
console.log(17 % 5, 10 % 2 === 0);           // remainder; checks even numbers

// a whole random number between min and max, both included
const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const roll = randomInt(1, 6);
console.log(roll >= 1 && roll <= 6);

The pattern: for a random whole number between min and max, scale random, floor it, then shift it up by min.

Terminal OUTPUT
$ node math.js
9 1
75
8 1024 9
2 true
true
05

Decimal gotchas

Understand why 0.1 + 0.2 is not 0.3, handle money safely and use BigInt for huge whole numbers.

AccuracyEPSILONBigIntMust know

Computers store decimals in binary, and some simple decimals like 0.1 cannot be stored exactly, the same way 1/3 never ends in decimal. The error is tiny, but it shows up when you compare.

ProblemFix
Comparing decimalscheck the gap is below Number.EPSILON
Adding moneycount whole paise or cents, divide only for display
Whole numbers above 9 quadrillionuse BigInt, written with an n on the end
gotchas.jsJAVASCRIPT
console.log(0.1 + 0.2);                  // tiny error from how decimals are stored
console.log(0.1 + 0.2 === 0.3);

const close = (a, b) => Math.abs(a - b) < Number.EPSILON;
console.log(close(0.1 + 0.2, 0.3));     // compare with a tiny allowed gap

// for money, count the smallest unit (paise) as whole numbers
const paise = 10 + 20;                  // ₹0.10 + ₹0.20
console.log(paise / 100);

console.log(Number.MAX_SAFE_INTEGER);
console.log(9007199254740993);           // too big: the last digit is lost
console.log(9007199254740993n + 1n);     // BigInt, with n, stays exact

Rule of thumb: never store money as rupees with decimals. Store paise as a whole number and format it at the very end.

Terminal OUTPUT
$ node gotchas.js
0.30000000000000004
false
true
0.3
9007199254740991
9007199254740992
9007199254740994n
06

Show it nicely

Format numbers for people: thousands separators, currency, percent and short forms like 2.4M.

FormattingtoLocaleStringIntl.NumberFormat

Picture it: formatting

1234567.891Intl.NumberFormat("en-IN", { currency })₹12,34,567.89The number stays the same. Only how it looks changes.
toLocaleString(locale)

Adds separators the way that country writes numbers.

See the example
Gives a stringMakes a new one
Intl.NumberFormat(locale, options)

Builds a reusable formatter for currency, percent or compact numbers.

See the example
Gives a formatterMakes a new one
format.jsJAVASCRIPT
const amount = 1234567.891;

console.log(amount.toLocaleString("en-IN"));   // Indian grouping: lakhs and crores
console.log(amount.toLocaleString("en-US"));

const inr = new Intl.NumberFormat("en-IN", { style: "currency", currency: "INR" });
console.log(inr.format(amount));

const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
console.log(usd.format(amount));

const pct = new Intl.NumberFormat("en-IN", { style: "percent", maximumFractionDigits: 1 });
console.log(pct.format(0.1834));

const short = new Intl.NumberFormat("en-US", { notation: "compact" });
console.log(short.format(1500), short.format(2_400_000));

Why it matters: en-IN groups by lakhs and crores while en-US groups by thousands. Make the formatter once and call format as often as you like.

Terminal OUTPUT
$ node format.js
12,34,567.891
1,234,567.891
₹12,34,567.89
$1,234,567.89
18.3%
1.5K 2.4M
07

All together

Split a restaurant bill with tax between friends, down to the last paisa.

Putting it togetherMath.round%Intl

Splitting ₹859.43 three ways does not divide evenly. This example works in whole paise so nothing gets lost, then hands the leftover paise to the first people so the shares still add up to the total.

bill.jsJAVASCRIPT
// split a restaurant bill fairly, working in paise so nothing is lost
const items = [
  { name: "Paneer tikka", price: 349.0 },
  { name: "Dal makhani", price: 289.5 },
  { name: "Naan x4", price: 180.0 },
];
const people = 3;
const GST = 0.05;

const toPaise = (rupees) => Math.round(rupees * 100);
const subtotal = items.reduce((sum, item) => sum + toPaise(item.price), 0);
const tax = Math.round(subtotal * GST);
const total = subtotal + tax;

// share out the paise, and give any leftover to the first people
const base = Math.floor(total / people);
const leftover = total % people;
const shares = Array.from({ length: people }, (_, i) => base + (i < leftover ? 1 : 0));

const inr = new Intl.NumberFormat("en-IN", { style: "currency", currency: "INR" });
console.log("total", inr.format(total / 100));
console.log(shares.map((p) => inr.format(p / 100)).join(" | "));
console.log("adds up:", shares.reduce((a, b) => a + b) === total);

What each part uses: whole paise from module 05, Math.round and Math.floor from 03, the remainder operator from 04, and Intl.NumberFormat from 06.

Terminal OUTPUT
$ node bill.js
total ₹859.43
₹286.48 | ₹286.48 | ₹286.47
adds up: true
TerminalBASH
# save any example as a file and run it with Node 22
$ node bill.js
# or paste it into your browser console with F12

Which one do I need?

Start from what you want to do, then read across to the tool and what it gives back.

I want toUseYou get
Check for a whole numberNumber.isInteger(n)true or false
Check for NaNNumber.isNaN(n)true or false
Turn text into a numberNumber(text)a number or NaN
Read "42px" as 42parseInt(text, 10)a number
Round to nearestMath.round(n)a whole number
Show 2 decimalsn.toFixed(2)a string
Find the biggestMath.max(...list)a number
Check even or oddn % 2 === 0true or false
Random from 1 to 6Math.floor(Math.random() * 6) + 1a whole number
Compare decimalsMath.abs(a - b) < Number.EPSILONtrue or false
Huge exact numbers123na BigInt
Show as rupeesIntl.NumberFormat("en-IN", { style: "currency", currency: "INR" })a formatter