Comparing Floats Without ==
akb825 Wrote:BTW, I noticed in your source that you're using ==. Don't. With floats, you want to subtract them, take the absolute value and see if the result is < some epsilon.
I noticed that in another thread and wondered if anyone could elaborate on what exactly he's talking about. I'm not sure I understand.
What I think is going on is this:
Code:
float a = 5.3423043f;
float b = 23.432532f;
float epsilon = .002f;
if(fabs(ab) < epsilon)
//do stuff
Is that correct?
Edit: Subquestion: why do this instead of ==?
Yes, that's correct. The epsilon I've been using lately is 1e5.
The reason why this is necessary is because you aren't guaranteed to have exactly the same number in the smallest parts of your precision due to rounding. Say you have 2 numbers that you've calculated: 2.948000021 and 2.948000342. You may want those to be equal, but they won't show as equal with a == check. No matter how careful you are, if you do any operations on a number that change it, it's almost always going to have a small rounding error at the end.
If you google the subject, you'll find plenty of information about it. You'll also find a more general rounding case for numbers that aren't close to 0, but for numbers that are relatively close to 0, the subtract and check is pretty much the easiest way to do it. (and you don't have to worry about a special case when one of them is 0)
The reason why this is necessary is because you aren't guaranteed to have exactly the same number in the smallest parts of your precision due to rounding. Say you have 2 numbers that you've calculated: 2.948000021 and 2.948000342. You may want those to be equal, but they won't show as equal with a == check. No matter how careful you are, if you do any operations on a number that change it, it's almost always going to have a small rounding error at the end.
If you google the subject, you'll find plenty of information about it. You'll also find a more general rounding case for numbers that aren't close to 0, but for numbers that are relatively close to 0, the subtract and check is pretty much the easiest way to do it. (and you don't have to worry about a special case when one of them is 0)
Just be aware that using an unjustified epsilon is detrimental to precision. Ideally, your epsilon should reflect the maximally expected numerical error in your algorithm.
This might be compiler specific, but it's not ok to do this:
Is it?
Almost wrote that in before I realized the possible mistake and calculated 1e5.
Code:
#define MY_EPSILON 1e5
Is it?
Almost wrote that in before I realized the possible mistake and calculated 1e5.
Why would that not be OK?
To expand on DoG's post, check out the EPSILON is NOT 0.00001! presentation from GDC 2005 (unfortunately it's power point but works OK in OpenOffice).
OneSadCookie Wrote:Why would that not be OK?
Because I've never defined a formula in scientific notation like that, didn't think it was possible. *shrug*
it is.
I believe there's a predefined epsilon buried in libc somewhere.. it might be too small for you purposes; float might be inaccurate enough to falsely pass the test...
Ahh yes, the constant is FLT_EPSILON, found in float.h
I believe there's a predefined epsilon buried in libc somewhere.. it might be too small for you purposes; float might be inaccurate enough to falsely pass the test...
Ahh yes, the constant is FLT_EPSILON, found in float.h
It's not magic, it's Ruby.
Actually, you've got it backwards: it would be inaccurate enough to falsely fail the test.
Nayr Wrote:it is.
I believe there's a predefined epsilon buried in libc somewhere.. it might be too small for you purposes; float might be inaccurate enough to falsely pass the test...
Ahh yes, the constant is FLT_EPSILON, found in float.h
FLT_EPSILON is the smallest machine number (of a 32bit float) that, when added to one results in a number greater than one. eg:
1+EPS > 1
1+0.9*EPS == 1
If you are just randomly doing "if (foobar < MYEPS)" you are most likely doing it wrong. The machine epsilon is usually meant to be used as a relative number. Machine numbers can be hard to deal with, and a badly chosen eps will very likely screw up things and introduce more degenerate cases than it fixes. Ideally, you should choose the eps mathematically to match your algorithm, in the worst case at least by lots of testing and deliberation.
out of interest, why are you comparing floats?
It's not magic, it's Ruby.
I don't know about other people, but the main reason for me to compare floats in this way has been to eliminate equivalent vertices when optimizing my mesh. (that was also the context of my original statement)
akb825 Wrote:I don't know about other people, but the main reason for me to compare floats in this way has been to eliminate equivalent vertices when optimizing my mesh. (that was also the context of my original statement)
When I was doing similar work ( in my case, I wrote an API to let me declare meshes similarly to how you draw in immediate mode by drawing triangles and quads, and the backend would merge redundant vertices ) I collapsed similar vertices by ( expensively ) checking the squared distance between them, and collapsing if it was "close enough". In my case, "close enough" was defined on a persituation basis... but admittedly, my models are simple. That being said, it worked beautifully for me.
I think you said before that you just used display lists with your demo program. Is all of your drawing going to be done with immediate mode/display lists? (since, if so, using something like bonebased animations would be... difficult without transitioning to vertex arrays/VBOs)
Possibly Related Threads...
Thread:  Author  Replies:  Views:  Last Post  
f suffix on floats revisited  AnotherJake  2  2,931 
Dec 22, 2008 11:11 PM Last Post: Wowbagger 

Help with Floats  clapton541  1  2,127 
Apr 26, 2007 09:56 PM Last Post: PowerMacX 