A float (or a double) is imprecise simply because there are not enough digits in binary to represent any number with recurring decimals (well, binary decimals).
Let's say you wanted to display 1/10. In decimal notation, that's 0.10
and is exact. But on the computer, that is stored in binary, and "one tenth" in binary is a recurring number.
If you were to try to print one-tenth to 30 places:
float test = 1.0/10.0;
printf("%.30f", test);
You would get: 0.100000001490116119384765625000
A float value has 32 bits to work with:
- 1 bit to hold the sign
- 8 bits to hold the offset exponent ( which is the exponent + 127)
- and 23 bits to hold the significant digits
So, in the case of decimal value 0.1, it is represented in bits by
00111101 11001100 11001100 11001101
seeeeeee evvvvvvv vvvvvvvv vvvvvvvv
- s: the sign bit means it's positive
- e: exponent offset: 01111011 (123 in decimal) which means the exponent value is -4
- v: stored value
so, 0.1 decimal is represented as (in binary):
1.1001100 11001100 11001101 x 2^-4
(The leading 1. is implicit)
then, you can add up all the bit values:
0.500000000000000000000000000000 x 0
0.250000000000000000000000000000 x 0
0.125000000000000000000000000000 x 0
0.062500000000000000000000000000 x 1 <--- start here
0.031250000000000000000000000000 x 1
0.015625000000000000000000000000 x 0
0.007812500000000000000000000000 x 0
0.003906250000000000000000000000 x 1
0.001953125000000000000000000000 x 1
0.000976562500000000000000000000 x 0
0.000488281250000000000000000000 x 0
0.000244140625000000000000000000 x 1
0.000122070312500000000000000000 x 1
0.000061035156250000000000000000 x 0
0.000030517578125000000000000000 x 0
0.000015258789062500000000000000 x 1
0.000007629394531250000000000000 x 1
0.000003814697265625000000000000 x 0
0.000001907348632812500000000000 x 0
0.000000953674316406250000000000 x 1
0.000000476837158203125000000000 x 1
0.000000238418579101562500000000 x 0
0.000000119209289550781250000000 x 0
0.000000059604644775390625000000 x 1
0.000000029802322387695312500000 x 1
0.000000014901161193847656250000 x 0
0.000000007450580596923828125000 x 1 <<--- rounded up
added up equals:
0.100000001490116119384765625000
which is what you saw when you printed.
I've gone into more detail than you might have been asking about, but I wanted to illustrate exactly why using a float (or double) when dealing with finite amounts can end up giving you trouble.
If you multiply 4.2 * 100, you will get 419. Try it! The same principle applies.
For more intricate explanation with diagrams, see wikipedia:
http://en.wikipedia.org/wiki/Single_precision_floating-point_format
Brenda.