Link to home
Start Free TrialLog in
Avatar of calum
calum

asked on

anyone able to explain this???

i am using vc++ on win2k.

i was doing a simple loop, and found out that the code below behaves differently under release build and debug build.

it simply outputs integer i from 0 to 10 inclusive,
float f from 0 to 1 in steps of 0.1 inclusive,
float j from 0.25 to 2 in steps of 0.25 inclusive,
and double d from 0 to 1 in steps of 0.1 inclusive.

this works fine in debug build, BUT in release mode, float f only runs up to 0.9!!!

what is going on????? i attatch the exact code. i thought it may have something to do with doubles and floats, but float j works just fine in both modes.

i tried this:

#include <iostream>
using namespace std;

void main()
{

     for (int i = 0; i<=10; i++)
     {
          cout<<"i = "<<i<<endl;
     }

     for (float f = 0.0; f <=1.0; f+= 0.1)
     {
         
          cout<<"f = "<<f<<endl;
     }

     for (float j = 0.25; j <= 2.0; j+= 0.25)
     {
          cout<<"j = "<<j<<endl;
     }

     for (double d = 0.0; d < 1.0; d+= 0.1)
     {
          cout<<"d = "<<d<<endl;
     }
}
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image


Double WILL quit looping before d reaches 1.0.

Check your test:

for (; d < 1.0; d+= 0.1)

Kdo
Avatar of calum
calum

ASKER

err, running code above DOES run to 1

and it should have been
for (double d = 0.0; d <= 1.0; d+= 0.1)
    {
         cout<<"d = "<<d<<endl;
    }
which still runs to 1.

the problem i spotted was with float f, which does NOT run to 1

i;m confused!
It is always dangerous to do exact comparisons against floating point values: rounding errors may mean that the value is not quite what you expect.

It is always safest to do double comparison against an acceptable range that is respects the tolerance of the value, i.e. something like:

#include <math.h>

for (float f = 0.0; (f-1.0)<1e-6; f+= 0.1)
{
    cout<<"f = "<<f<<endl;
}

Avatar of calum

ASKER

what i don;t understand is how the float j in the example above runs thru till the end (last number 2) but the float f only runs to 0.9. Also, i don;t get how it works under debug mode but not release mode. i;m worried about a lot of other code i;ve written, tested in debug and then relied on the answers generated by release versions.
if you would just like a solution, i have tried various way, and finally this turn out to print the 1. but if you need explanation, sorry i don't know why either. :>

#include <iostream.h>
int main() {
   ...
   
   // declare another variable to test the condition
   float temp = 0.0;
   for ( float f = 0.0; temp <= 1.0; f += 0.1)
   {
      temp = f;
      cout<< "f = " << f <<endl;
   }
   ...
   return 0;
}

hope this help.
Avatar of calum

ASKER

thansk gotenks - but i;m looking for an explaination. particularly the difference in float f and float j, why one works and not the other, and why the difference between release and debug modes

calum
> but i;m looking for an explaination. particularly

As I mentioned, it is a rounding problem, i.e. in floating point aritmetic, the result of addition is only approximate.

As for the differences adding 0.25 may well be 'more stable' than adding 0.1 hence the difference.

For debug vs. release floating point arithmetic may be handled differently in release more - i.e. possibly with no checking or directly in hardware (FPU).

The point is that you should never compare floating point numbers directly for equality.  As I mentioned you should always allow some acceptable tolerance for rounding problems.
Avatar of calum

ASKER

that much i guessed. anyone got a definitive answer?

> anyone got a definitive answer?

what more do you want?  There is no more that I can think of - the problem is that floating point arithmetic is not exact.  What else is there to know?
Avatar of calum

ASKER

i;m concerned about the differencing between the debug and release builds handling the floats differently
ASKER CERTIFIED SOLUTION
Avatar of jasonclarke
jasonclarke

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of calum

ASKER

fair enough. it is quite important as i;m doing some maths stuff. maybe i;ll just use doubles ... i don;t want to have some tolerance check on every comparison i do - i do loads of them.

you get the points, thanks for your help
> maybe i;ll just use doubles

even this is not entirely safe.  If it is important then you really should use a tolerance value.  You can wrap it up in a function if you like:

const float tolerance = 1e-6;

inline bool floatEquals(float f1, float f2)
{
    return fabs(f1-f2) < tolerance;
}

inline bool floatLTE(float f1, float f2)
{
    return f1-f2 < tolerance;
}

then

for (float f = 0.0; floatLTE(f,1.0); f+= 0.1)
{        
   cout<<"f = "<<f<<endl;
}