Sign in to follow this  
JohnHurt

Debug vs Release Mode Nightmare [solved]

Recommended Posts

Hi guys, This problem has got me tearing my hair out. Can anyone tell why this code (win32 console app) will work correctly in Debug mode, but not in Release mode in Visual Studio .NET 2003? In Release mode the condition which leads to the app printing "here" does not get met, even though mathematically it should be true. In debug mode it works fine. I've tried deleting all the intermediary files and rebuilding, and I've installed the latest service pack, but to no avail. I'd really appreciate someone shedding some light on this, because I really can't see it myself.
#include <stdlib.h>
#include <stdio.h>

#include <math.h>

///////////////////////////////////////////////////////////////////////////////////////
// gtVector - 3 dimensional vector
class gtVector
{
public:
	float x, y, z;

	// constructors
	gtVector();
	gtVector(const float &x, const float &y, const float &z);
	
	// other operations
	float Magnitude() const;
	gtVector Normalise() const;
};
///////////////////////////////////////////////////////////////////////////////////////

float gtVector::Magnitude() const 
{
	return sqrtf(x * x + y * y + z * z); 
}

gtVector gtVector::Normalise() const 
{
	float len = Magnitude();
	
	if ( len == 0.0f )
		return gtVector();
	return gtVector(x / len, y / len, z / len);
}

gtVector::gtVector() 
{ 
	x = 0.0f; 
	y = 0.0f; 
	z = 0.0f; 
}

gtVector::gtVector(const float &_x, const float &_y, const float &_z) 
{ 
	x = _x; 
	y = _y; 
	z = _z; 
}

int main()
{
	gtVector vNormal = gtVector(0,0,-55);
	vNormal = vNormal.Normalise();
	printf("%f\n", vNormal.z);

	if ( fabs(vNormal.z) == 1 )
	{
		printf("here\n");
	}
	
	system("pause");
	return 0;
}


[Edited by - JohnHurt on November 9, 2006 4:56:44 PM]

Share this post


Link to post
Share on other sites
Checking a float for equality (len == 0.0f, fabs(vNormal.z) == 1)
won't work because of the limited precision of floats/doubles.
Use a compare with an epsilon instead.

E.g.

#define FLOAT_CMP_EPSILON 0.00000001f

inline bool FloatCmp(const float &a, const float &b)
{
if (a > b - FLOAT_CMP_EPSILON)
{
if (a < b + FLOAT_CMP_EPSILON)
{
return true;
}
}
return false;
}

Share this post


Link to post
Share on other sites
You're working with floats, and these may be off by a tiny little amount. Don't compare the length to 1, but check if it's within a certain treshold of 1. I don't know how much it could be off, but it's probably not more than one millionth or such. I think. :)

EDIT: Got beaten to it. rating++ for the speed. ;)

Share this post


Link to post
Share on other sites
Short answer: optimisations can lead to some inaccuracies. This is perfectly normal.

"Long" answer:
There is no accurate floating point representation of 1/55. And optimized version of
gtVector(x / len, y / len, z / len)
usually becomes:
float lenInv = 1 / len;
gtVector(x * len, y * len, z * len)

as multiplication is usually faster than division. That's why you loose precision, even when you theoretically shouldn't. Precission loss is always to be considered. Whole another question is wheater this loss is always the same, or is it more or less random.

Also:
Quote:
Original post by deffer
I really recommend this article explaining in detail usage of /fp switch (Specify Floating-Point Behavior).

Share this post


Link to post
Share on other sites
The correct way is something like this iirc:


inline bool float_equal( float a, float b )
{
return fabsf( a - b ) <= std::max( 1.0f, std::max(a,b) ) * FLT_EPSILON;
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this