Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Float and !=

rup Eizenberg
Registered User
Join date: 23 May 2008
Posts: 31
01-26-2009 08:02
Can someone unstick the plank from my forehead.
Why does this create an endless loop?

float a=0;
float b=1;

while(a != b){
a+=0.1;
}

However this works as intended.

float a=0;
float b=1;

while((string)a != (string)b){
a+=0.1;
}


its not possible to use comparison with float
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
01-26-2009 08:13
Implicitly typecasting the integers 0 and 1 to floats a and b in your example might be the problem. I'm not in world to test, but try this ....

CODE

float a=0.0;
float b=1.0;

while(a != b){
a+=0.1;
}
rup Eizenberg
Registered User
Join date: 23 May 2008
Posts: 31
01-26-2009 08:21
just tried it out. same thing.

It is also to note that with the current example (a <= b) works, which unfortunatly doesnt help me really with the project i am on. so far the only thing working for me to "compare not equal" two floats is by using (string) but that doesnt make any sense to me thus far.
Sindy Tsure
Will script for shoes
Join date: 18 Sep 2006
Posts: 4,103
01-26-2009 08:25
Maybe doing this would show what's wrong..

CODE

float a=0.0;
float b=1.0;

while (a != b)
{
llOwnerSay ("a = " + (string)a + ", b = " + (string)b);
a+=0.1;
}
Dora Gustafson
Registered User
Join date: 13 Mar 2007
Posts: 779
01-26-2009 08:26
Never make a condition based on an exact Equal or Unequal with floating point numbers!
Never!
Make the program in a way so you can apply <= or >=
_____________________
From Studio Dora
Sindy Tsure
Will script for shoes
Join date: 18 Sep 2006
Posts: 4,103
01-26-2009 08:28
Yeah.. I don't like floats.. They're so.. er.. squishy.
Day Oh
Registered User
Join date: 3 Feb 2007
Posts: 1,257
01-26-2009 08:30
it's not possible to accurately store 0.1 in a float :)
_____________________
rup Eizenberg
Registered User
Join date: 23 May 2008
Posts: 31
01-26-2009 08:44
From: Day Oh
it's not possible to accurately store 0.1 in a float :)


So this is a math problem?
rup Eizenberg
Registered User
Join date: 23 May 2008
Posts: 31
01-26-2009 08:47
From: Dora Gustafson
Never make a condition based on an exact Equal or Unequal with floating point numbers!
Never!
Make the program in a way so you can apply <= or >=


i prefere the solution i found by converting with string as it fits better for what i am scripting.
Brief example

situation:
float a; //can be either greater or less then b
float b=0.5;

to use <= or => i would need two IF clauses one for each condition checking.
where as ( (string)a != (string)b ) is a one step deal.
RobbyRacoon Olmstead
Red warrior is hungry!
Join date: 20 Sep 2006
Posts: 1,821
01-26-2009 09:28
From: rup Eizenberg
So this is a math problem?

It's more of a representation problem, but you seem to get the point.

For a really good and short overview of the problem and possible solutions, I would point people to this blog post:

Here's an excerpt:
From: Christer Ericson


I will just note that absolute and relative tolerances are tested as

// Absolute tolerance comparison of x and y
if (Abs(x – y) <= EPSILON) …

and

// Relative tolerance comparison of x and y
if (Abs(x – y) <= EPSILON * Max(Abs(x), Abs(y)) …

The absolute tolerance test fails when x and y become large, and the relative tolerance test fails when they become small. It is therefore desired to combine these two tests together in a single test. Over the years at GDC, as well as in my book, I’ve suggested the following combined tolerance test:

if (Abs(x – y) <= EPSILON * Max(1.0f, Abs(x), Abs(y)) …

This typically works fine, but Erin Catto pointed out to me that it may sometimes be hard to control the desired behavior with just a single EPSILON that controls both the absolute and the relative tolerance at the same time. When better control is desired we can instead look at the combining of tolerances in the following way.

What we are really looking for in terms of equality of x and y is the following combined test:

if ((Abs(x - y) <= absTol) ||
(Abs(x - y) <= relTol * Max(Abs(x), Abs(y)))) …

These two expressions can be captured in a single formula as

if (Abs(x - y) <= Max(absTol, relTol * Max(Abs(x), Abs(y)))) …

or equivalently

if (Abs(x - y) <= absTol * Max(1.0f, relTol/absTol * Max(Abs(x), Abs(y)))) …



See the original post for more info.
_____________________
rup Eizenberg
Registered User
Join date: 23 May 2008
Posts: 31
01-26-2009 10:04
Thank You Robby

that pretty much explains it!
Pedro McMillan
SLOODLE Developer
Join date: 28 Jul 2007
Posts: 231
01-26-2009 10:05
EDIT: doh! Just realised most of this stuff was already mentioned above... should've read before posting! :\

It's worth noting that if the condition "a != b" doesn't work due to floating point representation, then "a < b || a > b" will fail for the same reason, since it is effectively the same thing.

However, if you'll only be dealing with known increments (e.g. of 0.1) then you could use "llAbs(a - b) >= 0.1". It's a bit less efficient, but it will accurately identify if the variables are not the same. You can change the condition operator to "<" if you want to check if they are roughly the same.

That kind of technique is used quite a bit in physical modelling for games, especially on platforms which don't support floating-point operations (although there's practically none of them any more). They would use fixed-point instead, storing and processing everything as integers, which is a lot faster, but numerically far less accurate (e.g. every number could quite easily be +/- 0.125, depending on the precision decided-upon, but for platforms like mobile (cell) phones, that's usually enough accuracy).