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.
Make and check
Write numbers, meet the special values NaN and Infinity, and test what kind of number you have.
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.
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.
$ node make.js number number 1000000 0.0025 Infinity -Infinity NaN NaN
Checks for a whole number with no decimals.
See the exampleChecks for a real, countable number. Not NaN, not Infinity.
See the exampleChecks for NaN without converting first.
See the exampleThe older check. It converts text first, so "hello" counts.
See the exampleconsole.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).
$ node check.js true false true false false true true false
Text to number
Turn what a person typed into a real number, and catch it when they typed something else.
| Input | Number(x) | parseInt(x, 10) | parseFloat(x) |
|---|---|---|---|
"42" | 42 | 42 | 42 |
"4.5" | 4.5 | 4 | 4.5 |
"42px" | NaN | 42 | 42 |
"" | 0 | NaN | NaN |
"abc" | NaN | NaN | NaN |
Converts the whole value. Any junk gives NaN.
See the exampleReads a whole number from the start, stopping at junk. Always pass 10.
See the exampleReads a decimal number from the start.
See the exampleA short way to write Number(x).
See the exampleconsole.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.
$ node parse.js 42 4.5 0 NaN 42 8 255 3.14 8 71 please enter a number
Round it
Round up, round down, cut off decimals, or show a fixed number of decimal places.
| Value | round | floor | ceil | trunc |
|---|---|---|---|---|
4.567 | 5 | 4 | 5 | 4 |
4.5 | 5 | 4 | 5 | 4 |
-4.5 | -4 | -5 | -4 | -4 |
To the nearest whole number. Halves go up.
See the exampleAlways down, towards minus infinity.
See the exampleAlways up.
See the exampleJust cuts the decimals off.
See the exampleRounds to that many decimals for display.
See the exampleconst 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.
$ node round.js 5 4 5 4 -5 -4 4.57 5 string 4.6 1.23e+3
Math toolbox
Find the biggest and smallest, powers and roots, remainders and random numbers.
Picks the biggest or smallest. Spread an array into it.
See the exampleRemoves the minus sign.
See the examplea to the power of b.
See the exampleThe square root.
See the exampleThe remainder after dividing. Great for even or odd checks.
See the exampleA random decimal from 0 up to, not including, 1.
See the exampleconsole.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.
$ node math.js 9 1 75 8 1024 9 2 true true
Decimal gotchas
Understand why 0.1 + 0.2 is not 0.3, handle money safely and use BigInt for huge whole numbers.
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.
| Problem | Fix |
|---|---|
| Comparing decimals | check the gap is below Number.EPSILON |
| Adding money | count whole paise or cents, divide only for display |
| Whole numbers above 9 quadrillion | use BigInt, written with an n on the end |
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.
$ node gotchas.js 0.30000000000000004 false true 0.3 9007199254740991 9007199254740992 9007199254740994n
Show it nicely
Format numbers for people: thousands separators, currency, percent and short forms like 2.4M.
Picture it: formatting
1234567.891Intl.NumberFormat("en-IN", { currency })₹12,34,567.89The number stays the same. Only how it looks changes.Adds separators the way that country writes numbers.
See the exampleBuilds a reusable formatter for currency, percent or compact numbers.
See the exampleconst 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.
$ 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
All together
Split a restaurant bill with tax between friends, down to the last paisa.
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.
// 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.
$ node bill.js total ₹859.43 ₹286.48 | ₹286.48 | ₹286.47 adds up: true
# 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 to | Use | You get |
|---|---|---|
| Check for a whole number | Number.isInteger(n) | true or false |
| Check for NaN | Number.isNaN(n) | true or false |
| Turn text into a number | Number(text) | a number or NaN |
| Read "42px" as 42 | parseInt(text, 10) | a number |
| Round to nearest | Math.round(n) | a whole number |
| Show 2 decimals | n.toFixed(2) | a string |
| Find the biggest | Math.max(...list) | a number |
| Check even or odd | n % 2 === 0 | true or false |
| Random from 1 to 6 | Math.floor(Math.random() * 6) + 1 | a whole number |
| Compare decimals | Math.abs(a - b) < Number.EPSILON | true or false |
| Huge exact numbers | 123n | a BigInt |
| Show as rupees | Intl.NumberFormat("en-IN", { style: "currency", currency: "INR" }) | a formatter |