I have this simple test:
double h;
...
// code that assigns h its initial value, used below
...
if ((h>0) && (h<1)){
//branch 1 -some computati
Since h
is a double, it may have been close enough to 1 to print as 1
, but it is actually a bit less than 1 so the comparison succeeds. Floating-point numbers do that a lot.
Short story: Your tests are incorrect because floating point numbers do not behave like you probably expect them to. Particularly things like "denom == 0" are problematic.
Sun has been nice enough to provide this paper online:
What Every Computer Scientist Should Know About Floating Point Arithmetic
which is exactly as advertised. Depending on your background it will be an easy read or a big of work, but it really is worth the time for any programmer using floats.
ADDED COMMENT: I'm not suggesting that every programmer will easily understand everything in that paper. Reading over it though will at the very least give a better idea of what floats actually are, what the issues are, and some hints on how to handle things properly.
If you want to do a lot of numerical work properly, you're going to have to read up on the various techniques, but that would be a textbook (or several) worth of material. The comments here have already pointed out some of the basics, and linked to more
The reason is that floating point numbers are not a real representation of the number that you save in the variable. (Opposed to BCD [binary coded decimals])
You can see the definition here: Floating Point Wikipedia
So the problem is that certain numbers are not expressable with a given set of bits. (You could if you could add bits infinitely) The trick is that in most cases the difference between the saved number and the intended number are pretty small. In practice, you have some corner cases where this may lead to problems. This is for example the reason why you should not build a financial software and use floating point numbers for money calculations. You can easily have differences that are noticeable, which your tax office won't like.
So to compare floating point numbers you should always apply some kind of threshhold that is ok for your application. Something like:
if(a==b)
becomes
if(abs(a-b)<threshold)
Edit: As David Mentioned in his comment, you will still get into trouble with things like pi, 1./3., ... But you can at least store numbers without loss in precision that you put into the system. As computers have limited memory you can always construct corner cases where you can't rely on exact representations...
Just saw your edit of the text, so here is the next edit:
if(a<1)
Is somehow harder, because you don't know whether it's just the number representation that is wrong or if it's just a real value that is close to 1. It really depends on the requirements for your algorithm. If a small error is ok, then do:
if(a < 1-threshold)
If it's not ok, then you have to use another variable type that is not suffering from the problem.
if you have to use floats in checks, round them off and store it in for example a integer. 1f could be 1.0000000000000000000000000000000001 or 0.999999999999999999999999999999999999
It could have to do with the fact that doubles in C/C++ are 64bit, but computation could be done at higher precision (the floating point registers of your cpu are wider (96 bit), so that not even a statement like cos(x)==cos(x) could be true.
Reference: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.18
You may be very interested in the Numerical Robustness for Geometric Calculations (aka "EPSILON is NOT 0.00001!") talk given at GDC 2005.