Number constants (MAX_SAFE_INTEGER, EPSILON…)

Every JavaScript number is a 64-bit float, including the ones that look like integers. These constants mark where that representation starts to lose information.

Number constantsES1 / ES2015Live demo
Common call
Number.MAX_SAFE_INTEGER
Returns
9007199254740991 — 2⁵³ − 1
Replaces
hard-coded magic numbers
Watch out
past it, n === n + 1 becomes TRUE
Number.MAX_SAFE_INTEGERMAX_SAFE_INTEGER — 2⁵³ − 1. The largest integer for which every integer up to it is exactly representable. MIN_SAFE_INTEGER is its negative.type: number · default: 9007199254740991, Number.EPSILONEPSILON — The gap between 1 and the next representable number — the standard tolerance for comparing floats near 1.type: number · default: 2.22e-16, Number.MAX_VALUEMAX_VALUE — The largest finite number. Anything above it is Infinity. MIN_VALUE is the smallest positive, about 5e-324.type: number · default: 1.79e+308…
→ number

Demo

Live evaluation
Try:
Inputs
nnumbera large integer
Output
[Number.isSafeInteger(9007199254740991), 9007199254740991 === 9007199254740991 + 1]
[true, false]

The pair is [is this a safe integer, does it equal itself plus one]. At MAX_SAFE_INTEGER the answer is [true, false] — everything behaves. Add one and it becomes [false, true]: the number is no longer exactly representable, so adding 1 produces the same value back. That is not a rounding display issue; the addition genuinely has no effect. Any id, timestamp in nanoseconds, or accumulated counter that crosses this line starts silently merging distinct values, which is why large integers from a backend should arrive as strings or be handled as BigInt.

Parameters

NameTypeRequiredDescription
MAX_SAFE_INTEGERnumberno (9007199254740991)2⁵³ − 1. The largest integer for which every integer up to it is exactly representable. MIN_SAFE_INTEGER is its negative.
EPSILONnumberno (2.22e-16)The gap between 1 and the next representable number — the standard tolerance for comparing floats near 1.
MAX_VALUEnumberno (1.79e+308)The largest finite number. Anything above it is Infinity. MIN_VALUE is the smallest positive, about 5e-324.

Return value

number — Each is a fixed numeric property describing a limit of the IEEE-754 double that every JavaScript number is.

Common patterns

Compare floats with a tolerance
EPSILON is the right scale near 1.
const equal = Math.abs(a - b) < Number.EPSILON;
Use BigInt past the safe range
Arbitrary precision, at the cost of interop.
const big = 9007199254740993n;
Keep large ids as strings
They are identifiers, not quantities.
const id = "9007199254740993";   // never parse it

Examples

1. The safe limit
Number.MAX_SAFE_INTEGER
Returns
9007199254740991
2. Past it, addition stops
2 ** 53 === 2 ** 53 + 1
Returns
true
3. Epsilon
Number.EPSILON
Returns
2.220446049250313e-16
4. The classic
0.1 + 0.2
Returns
0.30000000000000004
5. Compared properly
Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON
Returns
true
6. Overflow is Infinity
Number.MAX_VALUE * 2
Returns
Infinity

Pitfalls

1. Large integers silently lose precision
No error, no warning — arithmetic simply stops having an effect. Database ids, Twitter-style snowflake ids and nanosecond timestamps all exceed 2⁵³, and JSON.parse will happily produce a number that is already wrong by the time you see it.
Already corrupted
JSON.parse('{"id": 9007199254740993}').id
9007199254740992
Keep it a string
JSON.parse('{"id": "9007199254740993"}').id
'9007199254740993'
2. EPSILON is not a universal tolerance
It is the gap between 1 and the next double, so it is the right scale for values near 1 and far too small for large ones. Comparing two numbers around a million with EPSILON is the same as comparing them exactly.
Too strict up there
Math.abs(1e9 - (1e9 + 1)) < Number.EPSILON
false
Scale the tolerance
Math.abs(a - b) < Number.EPSILON * Math.max(Math.abs(a), Math.abs(b))
relative comparison
3. MIN_VALUE is not the most negative number
The name misleads. MIN_VALUE is the smallest POSITIVE number, about 5e-324 — a tiny fraction, not a large negative. The most negative finite number is -Number.MAX_VALUE.
Not negative at all
Number.MIN_VALUE
5e-324
The real minimum
-Number.MAX_VALUE
-1.7976931348623157e+308
4. Overflow gives Infinity rather than an error
Exceeding MAX_VALUE produces Infinity silently, and Infinity then propagates through every later calculation much as NaN does. Subtracting two infinities gives NaN, at which point the original cause is long gone.
Silent overflow
Number.MAX_VALUE * 2
Infinity
Check for it
Number.isFinite(result)
false

When to use

Use it
  • Bounds-checking integers before they lose precision
  • Tolerance-based float comparison, scaled appropriately
  • Detecting overflow after a large computation
  • Documenting why a value is handled as a string or BigInt
Reach for something else
  • Integers beyond the safe range → BigInt, or strings
  • Money → integer minor units
  • Exact decimal arithmetic → a decimal library
  • Comparing large floats → a relative tolerance, not EPSILON alone

Notes

Complexity
O(1) — these are plain properties
Return
Fixed numbers; all are non-writable and non-configurable
CPython impl
V8: number constants in the Number object setup
Memory
No allocation
Thread-safe
Single-threaded; the values never change

FAQ

Because neither 0.1 nor 0.2 can be written exactly in binary, any more than a third can be written exactly in decimal. Each is stored as the nearest double, and the two errors do not cancel. The result is 0.30000000000000004 — correct for the values that actually exist.

0.1 + 0.2;                                  // 0.30000000000000004
Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON;   // true

History

ES1
MAX_VALUE, MIN_VALUE, NaN and the infinities present from the first version.
ES2015
MAX_SAFE_INTEGER, MIN_SAFE_INTEGER and EPSILON added, naming limits developers had been hard-coding.
ES2020
BigInt arrived, giving exact integers beyond the safe range.