How a float is stored
IEEE 754 stores a number as sign × 1.fraction × 2exponent, in binary scientific notation. A 32-bit float has 1 sign bit, 8 exponent bits and 23 fraction bits; a 64-bit double has 1, 11 and 52. The exponent is stored with a bias (127 or 1023) so it never needs its own sign bit, and the leading 1 of the mantissa is not stored at all because it is always there for normal numbers.
| Sign | Exponent | Fraction | Bias | Decimal digits | |
|---|---|---|---|---|---|
| float32 (binary32) | 1 | 8 | 23 | 127 | ~7 |
| float64 (binary64) | 1 | 11 | 52 | 1023 | ~16 |
Why 0.1 + 0.2 is not 0.3
0.1 has no finite binary expansion, just as 1/3 has none in decimal. The nearest float64 is 0.1000000000000000055511151231257827…, and 0.2 and 0.3 are likewise slightly off. Adding the two rounded values and rounding again lands one unit away from the float nearest 0.3, so the comparison fails. Enter 0.1 above and look at the “exact stored value” row to see the rounding directly.
Special patterns
- Zero: exponent and fraction all 0. The sign bit still counts, so −0 exists and equals +0 in comparisons.
- Subnormal: exponent all 0, fraction non-zero. These are tiny values below the normal range, with reduced precision and no implicit leading 1.
- Infinity: exponent all 1, fraction 0. Produced by overflow and by division by zero.
- NaN: exponent all 1, fraction non-zero. Produced by 0/0, ∞−∞, sqrt(−1). NaN is not equal to anything, including itself.
Reading the bits by hand
- Split the pattern into sign, exponent and fraction fields.
- Subtract the bias from the exponent to get the real power of two.
- Put “1.” in front of the fraction bits (or “0.” for subnormals) and multiply by 2 to that power.
For 0x40490FDB: sign 0, exponent 10000000 = 128 → 128 − 127 = 1, fraction 1.1001001000011111101101 → 1.5707963 × 2 = 3.1415927, the float32 closest to π.
Questions
What is the difference between float and double?
A float (float32) uses 32 bits and gives about 7 significant decimal digits; a double (float64) uses 64 bits and gives about 16. Doubles are the default in most languages (JavaScript numbers, Python floats, C double); floats are used where memory or GPU bandwidth matters.
Why does the exponent use a bias instead of two's complement?
With a bias, floats with the same sign compare correctly as plain integers: a bigger bit pattern is a bigger number. That makes sorting and comparison cheap in hardware.
What is machine epsilon?
The gap between 1.0 and the next representable float: 2⁻²³ ≈ 1.19 × 10⁻⁷ for float32 and 2⁻⁵² ≈ 2.22 × 10⁻¹⁶ for float64. The gap grows with the magnitude of the number: at 2²⁴ a float32 can no longer represent odd integers.
What is the largest integer a double can store exactly?
2⁵³ = 9,007,199,254,740,992. Above that, consecutive integers are not all representable, which is why JavaScript has Number.MAX_SAFE_INTEGER (2⁵³ − 1) and BigInt.
Why does my language print 0.30000000000000004?
Because that is the shortest decimal that uniquely identifies the double you got from 0.1 + 0.2. Printing is correct; the stored value is what differs from 0.3.