This happens because the number of significant (decimal) digits in IEEE 754 single (aka "float) is about 7. Note that the first 7 non-zero digits of your numbers are correct (or become correct if you "round to nearest"). Why is this? Well, a single has a 23 bit significant (aka mantissa) (plus one implicit first bit that is always one), the rest is sign and exponent. So you basically have 23bit for the "exactness" of your number, in other words, for a given exponent you can have 8388608 different values (i.e. 7 correct decimal digits, neglecting that implicit first bit ).
N.B : My compiler version is gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
|
I am not completely sure, but I think there is a bug in that version, so it does not obey the standard IEEE 754 (it uses double rounding, meaning it computs floats with 80bit accurracy (performing 80-bit-rounding) and then rounds the result to 32 bit single). This is a common performance tweak (your fpu uses 80 bit internally anyways), but I think in that given compiler version it was not disabled with optimization turned off. So if you have other trouble with floating point arithmetic, try a different compiler (there are newer gcc versions...) and use -O2 as a maximal optimization, see also -funsafe-math-optimizations.
If you need "a little bit" better results, use "double"s, they have a 52bit significant.
If you want to do exact computations, have a look at libgmpxx, the Gnu Multiple Percision Library (C++ wrapper classes). They can perform exact rational arithmetic. If that isn't enough, have a look at LEDA::RAEL, which is exact for real algebraic numbers over Q (if that isn't enough, simplily your formulas or do it by hand ;-) )
You also could use floating point expansions. See e.g. Knuth's "Seminumerical Algorithms"-book.
Edit: Err, Knuth doesn't write about expansions, he just shows the formula to add *two* numbers exactly, using the machine instructions. Expansions were discovered later, I think. "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates" by Shewchuk might be the paper you want.