• Advertisement

Archived

This topic is now archived and is closed to further replies.

Comparing floats.

This topic is 5552 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, you have the basic |a-b| < e to check if two numbers are equal within some margin of error. That is the only way I can think of to do it. I saw a post here once where someone said they hated epsilons and never use them. So is there a practical alternative and if so what is it/are they? [edited by - LilBudyWizer on December 4, 2002 11:08:16 AM]

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
I guess you could divide them and see if you come close to 1...

Share this post


Link to post
Share on other sites
I think float''s (or maybe double''s, I forgot now , but this is still a good method) are accurate to 6 decimal places so you could do:

|a-b| < 0.000001

I just don''t remember now if float''s or double''s are accurate to 6 decimal places, but this works.

-timiscool999
"I like waffles. Especially with syrup." -me

XBox controller v2.0

click for bigger picture

Share this post


Link to post
Share on other sites
quote:
Original post by LilBudyWizer
Ok, you have the basic |a-b| < e to check if two numbers are equal within some margin of error. That is the only way I can think of to do it. I saw a post here once where someone said they hated epsilons and never use them. So is there a practical alternative and if so what is it/are they?



Nope, there are no alternative to epsilon with float. Simply because binary representation of a float is often inaccurate, for instance a simple number like 0.1 (or 0.2 or 0.3,... I don''t remember well)





----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
> |a - b| < e

This often works fine but occasionally it''s not good enough, usually when dealing with small or large numbers. E.g. if a and b are relatively large you will need to increase e otherwise you will almost never satisfy the condition. And if a and b are too small the converse applies: the condition will always be true unless e is made smaller.

There''s no hard and fast rule for this as what margin of error is acceptable, and how ''large'' or ''small'' you can go before it stops working, is very subjective, i.e. is largely a matter of opinion. One solution is to set it up in your game and have it print out |a - b| every time it does the test, then use this as a guidline to your value(s) of e.

> I guess you could divide them and see if you come close to 1...

As long as they are not too close to zero, as dividing by a small number tends to magnify errors, while dividing by zero gives an error.

Share this post


Link to post
Share on other sites
I can''t think of any practical/better way than using an epsilon. Did the person who mentioned that know what they were talking about? jk...

Basically, you want operations such as 5/5==10/10 to be equal, but it probably won''t be on most FPU hardware.

One problem I run into is, even with an epsilon, getting to the same number by a different way will sometimes be true, and sometimes false.

For example:
Suppose you''re seeing if 2 circles overlap.
epsilon = 0.1
distance = 1.0
radius = 0.51

These circles overlap and our function returns true. Then, another programmer learns of a faster way to compute the distance.
This function returns distance = 1.2
Now the circles don''t overlap.

The numbers are exaggerated, but sometimes logic can get messed up when something is both true and false.

FPU''s should have an epsilon right in their == operation (user-defined of course), although this doesn''t solve the problem above.

You could express your (semi-)real numbers as 2 integers.
Example: 4.5 is stored as 9 and 5 (9 / 5). All real numbers are converted to this format before any multiplications are done. After any mathematical operation the fractions are reduced. Comparison would then be perfect, but this solution is far from ideal. I''ll cut myself off here... look at the time, gotta go.

I''m thinking of changing my sig to "The world would be a better place without floats".

Share this post


Link to post
Share on other sites
Well, hopefully that would be 9/2 for 4.5, not 9/5, but I get the point. Sounds simple, but gets pretty nasty in practice. That is for a day I''m feeling a bit more ambiteous than just trying to compare two floating point numbers

Share this post


Link to post
Share on other sites
quote:
Original post by LilBudyWizer
Sounds simple, but gets pretty nasty in practice. That is for a day I''m feeling a bit more ambiteous than just trying to compare two floating point numbers

Oh, you wanted a PRACTICAL solution... my mistake

Share this post


Link to post
Share on other sites
quote:
Original post by johnb
> |a - b| < e

This often works fine but occasionally it''s not good enough, usually when dealing with small or large numbers. E.g. if a and b are relatively large you will need to increase e otherwise you will almost never satisfy the condition. And if a and b are too small the converse applies: the condition will always be true unless e is made smaller.

There''s no hard and fast rule for this as what margin of error is acceptable, and how ''large'' or ''small'' you can go before it stops working, is very subjective, i.e. is largely a matter of opinion. One solution is to set it up in your game and have it print out |a - b| every time it does the test, then use this as a guidline to your value(s) of e.




[note : the following is a rememberance of my sci. computation curses. Some details may be erroneous.]

Ah yes, I forgot that. In fact, float number are stored using scientifical notation, i.e a value between 0 (inclusive) and 1 (exclusive) and the power of 10.
e.g: 1 = 0.1e1.

Thus the |a - b| = X e N, hence epsilon is compared to _X_.

But I cannot remember the function to get the X value from a float.


----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
> But I cannot remember the function to get the X value from a
> float.

I think it''s the lowest 23 bits of the float, with the other bits being sign and exponent.

You could examine the appropriate bits to get the exponent, then divide by 2^n (as it''s a binary exponent) to adjust a and b before testing |a = b| < e. But this still has problems if a and/or b can be close to zero, as then the exponent grabbed from the numbers may be to small and so dividing by 2^n may generate too big errors.

Share this post


Link to post
Share on other sites
>Thus the |a - b| = X e N, hence epsilon is compared to _X_.

How can you be sure that your computer will store |a-b| so that _X_ can be compared to epsilon ?

Let''s say |a-b| = 1.0
then you can have |a-b| = 0.1 * 10^1 ("big") or = 0.00000000001 * 10^10 ("small") .


Tang

Share this post


Link to post
Share on other sites
quote:
Original post by Tangh
>Thus the |a - b| = X e N, hence epsilon is compared to _X_.

How can you be sure that your computer will store |a-b| so that _X_ can be compared to epsilon ?

Let''s say |a-b| = 1.0
then you can have |a-b| = 0.1 * 10^1 ("big") or = 0.00000000001 * 10^10 ("small") .


Tang



Again I forgot something important : the first digit after the decimal separator is not 0, thus 0.1 in is garanteed to be coded as 0.1E1 .


----
David Sporn AKA Sporniket

Share this post


Link to post
Share on other sites
ok, I see... but I suppose you actually compare the exponent of (a-b) with the smaller of the expo of a and b (instead of comparing X).

Tang

Share this post


Link to post
Share on other sites
Oh my god !!! the stuff about comparing the X part of |a - b| is just nonsense !!!!!!!

I apologize for writing such ****STUPID**** thing !!

=========================================================
Ok, I restart from the beginning :

let's say that 'a' is the reference, non zero value, then :

abs(a - b) is called "absolute error" and depends of the magnitude of a and b, thus so do epsilon.

abs((a - b)/a) is the "relative error" (relative to a) and it is independant from the magnitude of a and b, thus epsilon too.


[Edit] Ah, and if the reference is zero, well, obviously, we cannot use the relative error, of course.

----
David Sporn AKA Sporniket

[edited by - davidsporn on December 6, 2002 1:31:44 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Thrump
You could express your (semi-)real numbers as 2 integers.
...



Sorry to be a math-nazi, but you''d have a hard time representing irrational numbers this way (eg. pi, sqrt(2), e, etc.). You could store rational approximations to these numbers, but this hardly seems appropriate given your goal of eliminating the approximation built into the the binary representation of floating-point numbers.

A.P.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
>Sorry to be a math-nazi, but you''d have a hard time >representing irrational numbers this way (eg. pi, sqrt(2), e, >etc.). You could store rational approximations to these >numbers, but this hardly seems appropriate given your goal of >eliminating the approximation built into the the binary >representation of floating-point numbers.

of course you cant get the exact value of a rationnal number with a float, but who cares ? the goal wasnt to eliminate the approximations, but only to make sure these approx arent too bad. (and if there were no approx, the whole topic would be pointless)

Tang

Share this post


Link to post
Share on other sites

  • Advertisement