Floating-point number
Also known as: IEEE 754, double precision, binary64, float64, Number.MAX_SAFE_INTEGER, safe integer
A floating-point number stores a value as a binary fraction scaled by a power of two. JavaScript's Number is an IEEE 754 double with 53 significant bits, so integers above 2^53 − 1 (9,007,199,254,740,991) and most decimal fractions, 0.1 included, cannot be stored exactly.
Overview
An IEEE 754 double spends its 64 bits on one sign bit, 11 exponent bits and 52 fraction bits, with an implicit leading 1 that makes 53 significant bits in all. Its precision is relative rather than absolute: about 15 to 17 significant decimal digits at any magnitude, with the gap between neighbouring values doubling at every power of two. Every integer up to 2^53 is exact. Between 2^53 and 2^54 only even numbers exist, and between 2^60 and 2^61 neighbouring values are 256 apart.
Decimal fractions are the other half of the story. 0.1 has no finite binary representation, just as 1/3 has no finite decimal one, so it is stored as the nearest double, and those small errors surface in arithmetic: 0.1 + 0.2 evaluates to 0.30000000000000004. That is correct IEEE 754 behaviour, not a JavaScript bug — Python, Java and C produce the same result. Money should be held as integer minor units such as cents, or in a decimal type, never as a float.
Large integers are where floating point corrupts data silently. JSON's grammar allows any number of digits, but JSON.parse turns every number into a double, so 9007199254740993 becomes 9007199254740992 without any error, and RFC 8259 warns that interoperability is only assured for integers within ±(2^53 − 1). 64-bit IDs and nanosecond timestamps routinely exceed that. A nanosecond Unix timestamp passed 2^53 on 15 April 1970; today's values are around 1.75 × 10^18, where neighbouring doubles are 256 nanoseconds apart, so 1753524000123456789 parses as 1753524000123456768. That is why OpenTelemetry's JSON encoding and Discord's API send 64-bit integers as strings.
JavaScript offers exact alternatives. BigInt holds integers of any size exactly, although JSON.stringify throws on it. JSON.parse can now hand a reviver the original source text of each number, and JSON.rawJSON writes digits back out unchanged — in Chrome 114, Firefox 135 and Safari 18.4 onwards. The simplest fix of all is to keep large identifiers as strings from end to end.
Common questions about Floating-point number
Why does 0.1 + 0.2 not equal 0.3?
What is Number.MAX_SAFE_INTEGER?
Why does an ID or timestamp change when I parse JSON?
Does JSON itself limit numbers to 2^53?
How should money be stored?
Tools that work with Floating-point number
Related concepts
JSON
JSON (JavaScript Object Notation) is a lightweight text format for structured data — built from objects, arrays, strings, numbers, booleans, and null — that's become the lingua franca of web APIs, configuration files, and data interchange between services.
Unix Timestamp
A Unix timestamp is a single number counting the seconds elapsed since 1970-01-01T00:00:00Z, ignoring leap seconds — a time zone-free, language-agnostic way to name an exact instant, which is why it is what logs, databases, and APIs store internally.