Part 7 · 1 chapters · ~10 min
How Numbers Are Stored
Two's complement integers and overflow, IEEE 754 doubles bit by bit, why 0.1 + 0.2 printed 0.30000000000000004 on this machine, the 2^53 safe-integer limit and 64-bit ids, toFixed rounding surprises, and why money lives in integer minor units.
13
Bits with a rule for reading them
code
// printed by node on this machine (Apple M3 Pro)
> 0.1 + 0.2 0.30000000000000004
> 0.1 + 0.2 === 0.3 false
> let s = 0; for (…10 times) s += 0.1 0.9999999999999999
> 2**53 + 1 9007199254740992
> Number.MAX_SAFE_INTEGER 9007199254740991
> (1.005).toFixed(2) "1.00"
> 9007199254740993n 9007199254740993n // BigInt is exact
// money: integers in minor units, explicit rounding, format at the edge
const feeKobo = (amountKobo: bigint, bps: bigint) => (amountKobo * bps + 5_000n) / 10_000n; // half-up, basis points
const show = (kobo: bigint) =>
new Intl.NumberFormat('en-NG', { style: 'currency', currency: 'NGN' }).format(Number(kobo) / 100);
show(feeKobo(5_000_000n, 15n)); // 0.15% of ₦50,000 → "₦75.00"| value | safe type | never |
|---|---|---|
| money amounts | integer minor units; BigInt or decimal for large or fractional-rate maths | a JavaScript Number holding naira with decimals |
| 64-bit ids from the backend | string | JSON.parse into a Number (silent corruption above 2^53) |
| exchange rates | decimal string with stated precision | arithmetic on rounded display values |
| percentages in fees | basis points as integers | 0.015 multiplied in floating point |
HOW NUMBERS ARE STORED
two's complement, IEEE 754 doubles, why 0.1 + 0.2 is not 0.3, and why money is stored as integers
swipe the figure sideways, or tap expand for full screen
1/6
integers
Integers: n bits hold 2^n patterns. Two's complement makes the top bit negative, so 8 bits hold -128 to 127 and adding one to 127 wraps to -128. Hardware adds signed and unsigned numbers with the same circuit, which is why the format won. JavaScript's bitwise operators work on 32-bit two's complement.