🧮 Foundations — Before C
Floating point: scientific notation in bits
▶ Open the interactive lesson — free, no signupType 0.1 + 0.2 into almost any programming language and you can get back 0.30000000000000004. That famous glitch is not a bug — it's how every computer on Earth stores decimal numbers, and it's the reason banks never store money this way. By the end of this lesson the weirdness will make perfect sense, and you'll know the one comparison mistake with decimals that trips up nearly every beginner.
Integers can't hold 3.14 or 0.001. For real numbers, C gives you float (32-bit) and double (64-bit), both using the IEEE 754 standard — a rulebook nearly every computer agrees on, and essentially binary scientific notation.
Three fields in one number
Just like 6.022 × 10²³ has a sign, digits, and an exponent, a float splits its 32 bits into:
- 1 sign bit — positive or negative
- 8 exponent bits — where the point floats to (stored with a +127 offset)
- 23 mantissa bits — the significant digits (with a hidden leading 1)
Value = (−1)sign × 1.mantissa × 2exponent−127
▶ This spot has an interactive float32 widget — open the interactive lesson to play with it.
🧠 Checkpoint: A 32-bit float splits its bits as…
- 8 sign, 8 exp, 16 mantissa
- 1 sign, 8 exp, 23 mantissa
- 1 sign, 15 exp, 16 mantissa
- 2 sign, 10 exp, 20 mantissa
Show answer
1 sign, 8 exp, 23 mantissa — 1 + 8 + 23 = 32. A double is 1 + 11 + 52 = 64 bits.
The famous 0.1 problem
#include <stdio.h>
int main(void) {
double sum = 0.0;
for (int i = 0; i < 10; i++)
sum += 0.1;
printf("sum = %.17f\n", sum);
printf("sum == 1.0 ? %s\n", sum == 1.0 ? "yes" : "NO!");
return 0;
}$ gcc pointone.c -o pointone && ./pointone sum = 0.99999999999999989 sum == 1.0 ? NO!
Why?! Because 0.1 cannot be written exactly in binary — it's an infinite repeating fraction (0.000110011001100…), just like 1/3 = 0.333… in decimal. The computer stores the nearest representable value, and tiny errors accumulate.
Golden rule: never compare floats with ==. Compare against a tolerance: fabs(a - b) < 1e-9. And never use floats for money — count cents in integers instead.
🧠 Checkpoint: Why does 0.1 + 0.2 != 0.3 in floating point?
- A compiler bug
- 0.1, 0.2 and 0.3 have no exact binary representation
- Floats can only store integers scaled by 2
- printf rounds incorrectly
Show answer
0.1, 0.2 and 0.3 have no exact binary representation — Like 1/3 in decimal, 1/10 is an infinite repeating fraction in binary. Each constant is rounded to the nearest representable double, and the sums of the roundings differ.
Special values
IEEE 754 reserves exponent patterns for weird-but-useful values:
| value | how you get it | fun fact |
|---|---|---|
+∞ / −∞ | 1.0 / 0.0 | float division by zero doesn't crash! |
NaN (not-a-number) | 0.0 / 0.0, sqrt(-1) | NaN ≠ NaN — the only value not equal to itself |
−0.0 | -1.0 * 0.0 | equal to +0.0, but prints with a minus |
| denormals | values < ~1.2×10⁻³⁸ | graceful fade to zero (with reduced precision) |
🧠 Checkpoint: Which comparison is true in IEEE 754?
NaN == NaN-0.0 == 0.0INFINITY == NAN1.0/0.0 == 0.0
Show answer
-0.0 == 0.0 — Negative zero compares equal to positive zero. NaN is never equal to anything — even itself; that is actually how isnan() can be implemented.
float vs double: float gives ~7 significant decimal digits, double ~15–16. In C, unsuffixed literals like 3.14 are double; write 3.14f for a float. Default to double unless memory is tight.