Number in JavaScript: precision, limits, and reliable calculations
In JavaScript, number looks simple: you add, subtract, multiply, and divide. But once you work with money, percentages, large IDs, form data, or calculations that must be exact, important details appear. Understanding how Number works helps you avoid silent bugs and poor technical decisions.
One type for integers and decimals
JavaScript uses one number type for both integers and decimals:
console.log(typeof 42); // "number"
console.log(typeof 3.14); // "number"
console.log(3 === 3.0); // true
Internally, numbers use the 64-bit IEEE 754 format. This gives JavaScript a large numeric range, but it also introduces precision limits.
The classic problem: 0.1 + 0.2
Decimals cannot always be represented exactly in binary:
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
This is not a JavaScript bug. It is a consequence of floating-point numbers. To compare decimals, use a tolerance:
function nearlyEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(nearlyEqual(0.1 + 0.2, 0.3)); // true
For money, it is usually better to work in smaller integer units. For example, store cents instead of dollars:
const priceInCents = 1299;
const quantity = 3;
const totalInCents = priceInCents * quantity;
console.log(totalInCents); // 3897
NaN and Infinity
JavaScript includes special numeric values:
console.log(10 / 0); // Infinity
console.log(-10 / 0); // -Infinity
console.log(Number('hello')); // NaN
NaN means “Not a Number”, but its behavior can be confusing:
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // true
Use Number.isNaN() to check whether a value is really NaN. Avoid the global isNaN() when possible because it converts the value first and can produce surprising results.
Parsing numbers from strings
Input values arrive as text. To convert them:
const age = Number('25');
const price = Number.parseFloat('19.99');
const page = Number.parseInt('12', 10);
Number() requires the entire string to be numeric:
console.log(Number('12px')); // NaN
console.log(Number.parseInt('12px', 10)); // 12
That difference is useful, but it can also be dangerous. If you are validating forms, you usually want to detect invalid input instead of accepting a partial number.
Rounding and formatting
toFixed() returns a string, not a number:
const value = 12.345;
const rounded = value.toFixed(2);
console.log(rounded); // "12.35"
console.log(typeof rounded); // "string"
To display currency or locale-aware values, use Intl.NumberFormat:
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
});
console.log(formatter.format(1299.5));
Keep calculation and presentation separate: calculate with numbers, display with formatters.
Safe limits
JavaScript can represent very large numbers, but not every large integer is safe:
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.isSafeInteger(9007199254740992)); // false
If an ID comes from a database and exceeds that limit, do not treat it as a number. Store it as a string or use BigInt if you need mathematical operations.
BigInt
BigInt can represent integers larger than the safe integer limit:
const huge = 123456789012345678901234567890n;
console.log(typeof huge); // "bigint"
But you cannot mix number and bigint directly:
const count = 10n;
// count + 1; // TypeError
console.log(count + 1n); // 11n
Use it for large integers, not decimals or money with cents.
Math for common operations
The Math object includes common utilities:
console.log(Math.round(4.6)); // 5
console.log(Math.floor(4.6)); // 4
console.log(Math.ceil(4.1)); // 5
console.log(Math.max(3, 9, 1)); // 9
Math.random() is fine for simple random values, but not for security, tokens, or cryptography. Use crypto.getRandomValues() for that.
Best practices
- Convert strings to numbers explicitly.
- Validate with
Number.isNaN()andNumber.isFinite(). - Do not compare decimals exactly after floating-point operations.
- For money, use smaller integer units such as cents.
- Do not treat huge IDs as
number; use string orBigInt. - Use
Intl.NumberFormatwhen displaying numbers to users.
Conclusion
Number is enough for most everyday calculations, but it is not magic. Knowing where it loses precision, how to validate input, and when to use BigInt or integer money values helps you write more reliable software. Numeric bugs are often silent, so it is better to prevent them in the design.