Computers store most non-whole numbers as floating-point values: a sign, an exponent and a fraction, in the way scientific notation writes 1.6 × 10^-1. The IEEE 754 standard fixes the details, so a double behaves the same on every machine. The cost is that only some numbers can be stored exactly. Inspect any value with the IEEE 754 Float Converter, and compare the main number types in Float vs Double vs Decimal.
Sign, exponent, fraction
A binary floating-point number is (-1)^sign × 1.fraction × 2^(exponent - bias). The leading 1. is implied (a "hidden bit"), so a double gets 53 bits of precision from 52 stored fraction bits.
Worked example: 0.1
In double precision 0.1 is stored as the 64 bits 3fb999999999999a (hex): sign 0, exponent 1019 (that is 1019 - 1023 = -4) and fraction 0x999999999999a, which means roughly 1.6 × 2^-4. Because 1/10 has no finite binary expansion, the stored value is the nearest double:
0.1000000000000000055511151231257827021181583404541015625
The single-precision value 3dcccccd is 0.100000001490116119384765625. Neither equals 0.1; the error is simply too small to see in normal printing.
The common formats
| Format | Bits | Exponent bits | Fraction bits | Largest value | Smallest normal | Smallest subnormal | Spacing at 1.0 |
|---|---|---|---|---|---|---|---|
| half (binary16) | 16 | 5 | 10 | 65,504 | 6.10 × 10^-5 | 5.96 × 10^-8 | 9.77 × 10^-4 |
| single (binary32) | 32 | 8 | 23 | 3.4028235 × 10^38 | 1.1754944 × 10^-38 | 1.4 × 10^-45 | 1.19 × 10^-7 |
| double (binary64) | 64 | 11 | 52 | 1.7976931348623157 × 10^308 | 2.2250738585072014 × 10^-308 | 4.9 × 10^-324 | 2.22 × 10^-16 |
Special values
- Zero has a sign:
+0and-0compare equal but differ in some operations (1 / -0is-infinity). - Infinity results from overflow or division by zero. NaN (not a number) results from
0 / 0orsqrt(-1), andNaNis not equal to anything, itself included. - Subnormal numbers fill the gap between zero and the smallest normal number, trading precision for a gradual underflow.
Rounding surprises and safe habits
- Adding ten times 0.1 gives
0.9999999999999999, not 1. - Addition is not associative:
1e16 + 1 - 1e16is0, but1e16 - 1e16 + 1is1, because spacing near 10^16 is 2. - Never compare with
==. Testabs(a - b) <= tolerance, scaled to the size of the values. - Sum many numbers from smallest to largest, or use compensated summation.
- For money, use integers (cents) or a decimal type.