All three store numbers with a fixed number of digits, but float and double are binary (IEEE 754) while decimal types work in base 10. Inspect any value with the IEEE 754 Float Converter; the theory is in How Floating-Point Numbers Work and Floating-Point Number.
The types side by side
| float (binary32) | double (binary64) | decimal (e.g. decimal128) | |
|---|---|---|---|
| Total bits | 32 | 64 | 128 |
| Layout | 1 sign, 8 exponent, 23 fraction | 1 sign, 11 exponent, 52 fraction | Sign, exponent, up to 34 decimal digits |
| Precision | About 7 decimal digits | About 15-16 decimal digits | 34 decimal digits |
| Largest finite value | 3.4028235 × 10^38 | 1.7976931348623157 × 10^308 | 9.999… × 10^6144 |
| Machine epsilon | 1.19 × 10^-7 | 2.22 × 10^-16 | 10^-33 |
| Whole numbers exact up to | 16,777,216 (2^24) | 9,007,199,254,740,992 (2^53) | All with up to 34 digits |
| Represents 0.1 exactly | No | No | Yes |
The classic surprise
- In double precision
0.1 + 0.2is0.30000000000000004, and the nearestfloatto 0.1 is0.10000000149011612. - Above 2^24, a
floatcannot tell neighbouring whole numbers apart:16777216 + 1is still16777216. - In decimal arithmetic
0.1 + 0.2is exactly0.3(Pythondecimal). - Compare floats with a tolerance, never
==.
Which to use
- Graphics, audio, machine learning and games: float, where memory and speed matter more than the last digit.
- Science, statistics and general numeric code: double.
- Money, invoices, tax and anything people check by hand: decimal (or integer cents).
- Identifiers and large counters: integers, never floating point.