|
This thread is locked; no one can reply to it. |
1
2
|
AGAIN floats |
Frank Drebin
Member #2,987
December 2002
|
i want to write a function bool floats_are_equal(float a, float b) { return (fabs(a-b)<float_error); } with float_error=0.000001 because floats have 6 decimals or is there a better value i can take for this (do have floats a maximum inaccuracy i should take?)? |
Evert
Member #794
November 2000
|
Quote: because floats have 6 decimals Not exactly. Floats can store numbers with a certain precision (don't know if that's six or more, but that doesn't really matter), that precission does not depend on the order of magnitude of the number (because it is a floating-point number). Depending on your needs, 0.000001 could be a sufficient check. It really depends on what you want to do with it. |
spellcaster
Member #1,493
September 2001
|
First of all, you need to turn around the operator, or it'll return true if the floats are not equal. -- |
damage
Member #3,438
April 2003
|
If you are using C++, do this. #include <limits> using namespace std; ... cout << "Float has " << numeric_limits<float>.digits10 << " digits" << endl Secondly, don't use float. Use double, you get more precision for free, I am pretty sure. ____ |
Evert
Member #794
November 2000
|
doubles may be slower than floats (usually not an issue on modern hardware). |
gnolam
Member #2,030
March 2002
|
damage said: Use double, you get more precision for free, I am pretty sure. It's a trade-off between accuracy and speed. Frank Drebin said: with float_error=0.000001 because floats have 6 decimals or is there a better value i can take for this (do have floats a maximum inaccuracy i should take?)?
http://www.infosys.utas.edu.au/info/documentation/C/CStdLib.html#float.h -- |
Chris Katko
Member #1,881
January 2002
|
To my knowledge, doubles will normally be slower then floats until we go 64bit processors (doubles are 64bit). Unless in the case of using MMX, but then you have to reset the MMX registers and that takes up most of the gain, unless your doing batches of floating-point numbers. I may be wrong. I haven't been able to code in a long time so it may or may not be correct. -----sig: |
damage
Member #3,438
April 2003
|
Quote: doubles may be slower than floats (usually not an issue on modern hardware). That's true, but the vast majority of us will be programming on an x86 pentium or greater. From the pentium onward double and float have exactly the same speed, AFAICT. ____ |
A J
Member #3,025
December 2002
|
does the libc have #DEFINEs for floating point error for operations on floats ? ___________________________ |
Frank Drebin
Member #2,987
December 2002
|
the question isn't wehter using floats or doubles. |
Mars
Member #971
February 2001
|
Quote: the question isn't wehter using floats or doubles. Who are you blaming? They stayed relatively close to the topic! Quote: i'm going to use floats. but what value should i take You already have got some good replies. It depends on your application. If you're programming a game, then you need to take into consideration the accuracy of your engine. -- |
X-G
Member #856
December 2000
|
I'm still trying to figure out why exactly you need to do this comparison. So far, I've never had to do == checks on floats or doubles, simply because I've never come across any situation that would require it. -- |
Plucky
Member #1,346
May 2001
|
Frank Drebin
Member #2,987
December 2002
|
i use this because my coordinates of objects are stored in floats and because of movement and collision detection i have to compare them!!! --> so there are max 3 places before the point and now when there are 3 places behind the point left -> i should take a value like 0.001 ?!? |
X-G
Member #856
December 2000
|
Compare then, yes - but why == ? Collision detection usually just involves <= and >= ... -- |
Frank Drebin
Member #2,987
December 2002
|
that's true but for movement ( while (x_pos!=x_pos_to_reach) move_x();) or something like this sometimes ==/!= is nice. |
X-G
Member #856
December 2000
|
You could use use a threshold for that purpose and use </>. -- |
Fladimir da Gorf
Member #1,565
October 2001
|
You can use, for example: if( x_pos > x_pos_to_reach ) while( x_pos < x_pos_to_reach ) move_x(); else while( x_pos > x_pos_to_reach ) move_x(); I've never, ever yet needed to compare floats, and I don't think I'll ever need to. OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori) |
Frank Drebin
Member #2,987
December 2002
|
yes but i think mine is a bit shorter (easier). |
Fladimir da Gorf
Member #1,565
October 2001
|
"i don't like floats very much too " Who said I didn't like floats? When was the last time I didn't use floats (or doubles) for movement? I don't like comparasions between them, just because you may not reach the destination, depending on the speed of the object. "yes but i think mine is a bit shorter (easier)." Yes, but mine works. OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori) |
Andrei Ellman
Member #3,434
April 2003
|
evert said:
Quote: An IEEE-754 floating point number is represented by a sign-bit, an exponent, and a mantissa. The precision of a floating point number depends only on the number of bits in the mantissa-portion, and the range of it's order of mangitude depends on the number of bits in the exponent, so talking about the "number of decimals" does not make sense with floating point numbers (unless the exponent is always the same - hence 'fixed-point numbers'), but the "number of significant digits" does. A floating point number is worked out from it's stored representation using ( 1 - 2*sign ) * 2^(exp - exp-bias) * ( 1 + mantissa / mantissa-divisor ) A single precision floating point number (a 32-bit 'float') uses 1 sign-bit, 8 exponent-bits and 23 mantissa-bits, so exp-bias would be 127 (2^8 - 1 - 2^(8-1)) and mantissa-divisor would be 8388608 (2^23). The number of significant digits in base 10 a floating point number can store is calculated as: For more information and much better explanations than what I've written here, see the following web-pages:
</li> etwinox said: To my knowledge, doubles will normally be slower then floats until we go 64bit processors (doubles are 64bit). Unless in the case of using MMX, but then you have to reset the MMX registers and that takes up most of the gain, unless your doing batches of floating-point numbers. The MMX is used to do similar operations in paralell on sets of data, but MMX only works for integers (or fixed point numbers with tweaking of the input/output). MMX does not work with floats/doubles. [edit2:] SSE which is a newer extension than MMX is like MMX but works with floats. SSE2 (only found so far on Pentium 4's) is similar but uses doubles. damage said:
Quote: I think that internally, the Pentium will perform operations at the same speed on doubles and floats as long as the values are stored within the CPU's FPU registers (not sure on this). What I am sure of is that on a 32-bit processor (IA32) such as the Pentium and many of it's successors, there is only a 32-bit bus between the CPU and memory, so the CPU can read/write a 32-bit float (32-bits) in one memory-fetch, and it takes two memory-fetches to read/write a 64-bit double to memory, and three to read an 80-bit number (question: is this what a 'long double' is or does it have even more bits?). On an IA64 processor, it can work with doubles and floats at the same speed (unless there's some sort of optimisation that involves reading in two adjacent floats in memory at once). Also, the x87 FPU (floating point component of any x86-based chip) uses 32-bits for short floating-point numbers, and 80-bits for long floating point numbers. I don't think it can natively work with 64-bit numbers without expanding them to 80 bits. This means that the x87 FPU will not generate overflows or underflows that would be generated by doing the same calculations using a 64-bit FPU. Plucky said:
Try: The above code uses divides. That will significantly slow down any code that does a lot of comparisons. IMO, that's just overkill! [edit1:] perhaps an optimised version of this could be written that works by adding to or subtracting from the bits of the IEEE-754 float's exponent instead of using divides, but that would make it non-portable. AE. -- |
Plucky
Member #1,346
May 2001
|
Quote: The above code uses divides. That will significantly slow down any code that does a lot of comparisons. IMO, that's just overkill! The code, or something like it, is necessary if you want to compare floats across its whole dynamic range. Otherwise something like what Frank first suggested would work if you knew what range all the float comparisons would be operate in. [edit] Perhaps we should add floating point questions to the list of questions that pop up weekly or bi-weekly. I bet we already have a dozen posts that go through the details of the floating point implementation. |
Andrei Ellman
Member #3,434
April 2003
|
Plucky: See the edit1 to the above post for a possible means of optimising it. -- |
Plucky
Member #1,346
May 2001
|
I'm not sure playing with the bits and probably adding one or two conditionals to handle special cases would be faster. Someone would of course need to code both methods and test them to be sure. |
Korval
Member #1,538
September 2001
|
Quote: that's true but for movement ( You aren't looking for a generalized ==/!= floating-point test. What you want is to test whether or not the given Vec2 is within a particular box. The size of the box depends on the accuracy you care about. If this is a 2D game, the accuracy you care about is to the nearest pixel. So, just do an "(int)" cast operation to the floats in question. If this is a 3D game (or, for some reason, you need better-than-per-pixel-accuracy), then I would suggest a more flexible system than, "Is he at position Vec2 yet?" I would, instead, suggest that all movements be normalized on the range 0.0f-1.0f. Let's say you have the initial position Vec2i, and the final position Vec2f. The direction towards the final position is Normalize(Vec2f-Vec2i). Let's call that Vec2Dir. The distance between these two points is Dist. Given that this is a game, you probably have some speed that the object moves. Let us call that Speed. The objective now is to create a function F(t), such that F(0.0f) == Vec2i, and F(1.0f) == Vec2f. Why is this good? Because it makes telling when you're done with the movement trivial. You just clamp 't' such that it is never greater than 1.0f. When t==1.0f (a perfectly fine comparison, considering that your clamp function just set it to 1.0f), the movement is finished. So, what is F(t)? Well, F(t) = Vec2i + (Vec2Dir * Dist * t). Simple enough, right? The Vec2Dir gets it pointing in the right direction. Dist * Vec2Dir + Vec2i == Vec2f (given the definitions of Dist and Vec2Dir). And t=0 means that F is Vec2i. Just what we need. Of course, it isn't precisely what you need, because the time scale of t is all wrong. You have some speed for the object. And you're taking particular timesteps. Therefore, you need to be able to feed in a time delta into F(t). Which means, you need a new function t(time) such that you can build the useful function G(time). Well, given the speed Speed of the object, you know that it will take TimeScale = Dist / Speed seconds to go from the initial position to the final. As such, the function t(time) = time / TimeScale. Therefore: G(time) = Vec2i + (Vec2Dir * Dist * (time / TimeScale)); What if the speed changes during the travels? Well, you will have to reset the variables every time the speed changes. Vec2i becomes the current location, and you have to recompute Dist and TimeScale (Vec2Dir shouldn't have changed, but you get it for free). Obviously, if the object isn't going in a straight line from point A to point B, that's a different issue. In that case, use the box method, and pick whatever accuracy you need (tenths, 0.001, etc). Do not, however, think of it as a generalized floating-point equality test. This is to be used only for the purpose of determining whether a particular Vec2 is at a particular position in the world. This function should be used only for that. |
|
1
2
|