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;
}
}
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;
}
}
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!
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!
I just got some points from here
https://www.experts-exchange.com/questions/20548837/If-Else-problem-with-floating-point-numbers.html
https://www.experts-exchange.com/questions/20548837/If-Else-problem-with-floating-point-numbers.html
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;
}
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;
}
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.
#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.
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
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.
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.
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?
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?
ASKER
i;m concerned about the differencing between the debug and release builds handling the floats differently
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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;
}
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;
}
Double WILL quit looping before d reaches 1.0.
Check your test:
for (; d < 1.0; d+= 0.1)
Kdo