float/double unpredicted calculation results

Started by
3 comments, last by Conner McCloud 19 years, 6 months ago
We are trying to compare to floats in an ifstatement and after some debugging we traced the problem to float'ing calculation problem. The program below where compiled in Borland 5.02 but the problem where first spotted in Visual 6.0. But in Visual both the float and double calculations are wrong. We dont need more than 3-4 decimals precision but the problem are ruin the ifstatements. We wonder if there is any way to solve this problem.

int main(void) {
	float fl1 = 0.0;
   double db1 = 0.0;
   long counter = 0;
   while (counter<=4000) {
   	counter++;
      fl1 -= 0.001f;
      db1 -= 0.001;
   }
   printf("1%.10f", fl1);
   cout << "\n";
   printf("1%.10f", db1);
   getch();
}


Results:
-4.0008926392
-4.0010000000

Advertisement
You are simply witnessing the drawbacks of storing floating point numbers in a base 2 system. It is simply not possible to store certain floating point values in this system. There are many nice articles about this issue. Here is one.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
Welcome to the world of floating point imprecision. The internal representation of floating point numbers is only approximate. Therefore, identical operations on floats and doubles cannot be gauranteed to produce the same results, and seemingly predictable operations on either (such as adding .1 to 0 10 times) cannot be gauranteed to produce the expected results (10).

One common solution is to introduce an epsilon value into your calculations, i.e. two numbers are equal if they are within some small interval of each other. Common epsilons are .01, .001, etc., but it really depends on the scale of your application what is appropriate. Quake uses 1/32, which is actually pretty big.

In game applications, typically you just want to avoid relying on == and != operators when it comes to floats and doubles. Find ways to use <, >, <= and >= instead.
0.1*2=0.2, 0.2*2=0.4, 0.4*2=0.8, 0.8*2=1.6, 0.6*2=1.2 and you are back to 0.2. So 0.1 in decimal is 0.0001100110011... in binary or more precisely 0.1=sum(2^(-4n)+2^(-4n-1),n,1,infinity). Generally it is best not to accumulate the errors in representation. So fll=(counter+1)/1000.0f.
Keys to success: Ability, ambition and opportunity.
Quote:Original post by Asker
We are trying to compare to floats in an ifstatement and after some debugging we traced the problem to float'ing calculation problem. The program below where compiled in Borland 5.02 but the problem where first spotted in Visual 6.0. But in Visual both the float and double calculations are wrong. We dont need more than 3-4 decimals precision but the problem are ruin the ifstatements. We wonder if there is any way to solve this problem.

*** Source Snippet Removed ***

Others have explained the floating point issues, so I would just like to suggest not mixing 'printf' with 'cout'. They might maintain separate buffers, and when they happen to get flushed to the screen will determain what order you actually see stuff in. That was a problem for me once, it took me a while to realize what was going on.

CM

This topic is closed to new replies.

Advertisement