Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


float vs double


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
49 replies to this topic

#41 Promit   Moderators   -  Reputation: 7675

Like
0Likes
Like

Posted 08 September 2005 - 06:27 PM

Quote:
Original post by RobTheBloke
on the bog standard 0x86 FPU, all calcs happen at 80bits, whether they are double or float. however, the 0x86 can read only 4bytes at a time. So (assuming that the data is 4byte aligned), a double requires 2 reads to get it into memory, a float requires a single read.


Just to clarify, entire blocks of 4k will be read out of main memory and into L1 cache at a time. These will then be loaded into registers as needed. The latter step isn't especially intensive. The thing is though, that the 4k will only fit half as many doubles as floats.

Sponsor:

#42 HalcyonX   Members   -  Reputation: 130

Like
0Likes
Like

Posted 08 September 2005 - 07:21 PM

Quote:
Original post by Daniel Miller
If you shouldn't use == or !=, then wouldn't > and < be messed up as well?


No, < and > are fine. The problem with == and != is that rounding errors could turn what you think is 1.234567 into 1.234693, and if you try to == it with 1.234567, it'll return false, when it actually should be true. On the other hand, 1.234693 is still, say, < 0. You only have a problem if you compare 2 numbers that are very close to each other.

#43 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 08 September 2005 - 09:00 PM

at university they told us that some implementations tend to round up the last bit of the mantissa if you have a large positive exponent

although i don t know why they don t implement a hardware epsilon comparsion since the binary comparsion is
a) actually quite useless in most cases
b) could be don t by integer comparsions or bitwise and
(float pointer to intpointer, reference & right operand)

#44 kSquared   Members   -  Reputation: 1356

Like
0Likes
Like

Posted 09 September 2005 - 06:10 AM

Quote:
Original post by MauMan
Quote:

NEVER EVER use == on a float


Sometimes I've thought to myself that using == or != on a float or double should arguably be a compiler warning.

I have to disagree. It's the best way to test for NaN. For instance,
f != f   // returns true if f is NaN
f == f // returns false if f is NaN
f == NaN // always returns false
f != NaN // always returns true


I usually use a utility method to determine if numbers are sufficiently close, e.g.,
public static bool EpsilonEquals(double f1, double f2, double epsilon)
{
// Returns true if f1 is closer than epsilon to f2.
return (Math.Abs(f1 - f2) <= epsilon);
}

or for inequalities,
public static bool EpsilonGreaterThan(double f1, double f2, double epsilon)
{
// Returns true if f1 is greater than f2 within tolerance.
return ((f1 - epsilon) > f2);
}


public static bool EpsilonGreaterThanEqualTo(double f1, double f2, double epsilon)
{
// Returns true if f1 is greater than or equal to f2 within tolerance.
return ((f1 - epsilon) >= f2);
}


#45 BittermanAndy   Members   -  Reputation: 108

Like
0Likes
Like

Posted 09 September 2005 - 07:49 AM

Quote:

Very true, a most useful function for any program dealing with floating values:

bool compareFloat ( float Value1 , float Value2 , float Tolerance )
{
if ( fabs ( Value1 - Value2 ) < Tolerance )
return true ;
else
return false ;
}

The tolerance can be hard coded if desired.


Actually, that's an improvement over == but still not great... http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm explains why, and suggests better methods. (Anyone know how to make that a link? I tried [url] but that doesn't work).

#46 MaulingMonkey   Members   -  Reputation: 1556

Like
0Likes
Like

Posted 09 September 2005 - 09:20 AM

Quote:
Original post by BittermanAndy
(Anyone know how to make that a link? I tried [url] but that doesn't work).


Use HTML.

<a href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm">http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm</a>
->
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm


#47 Raghar   Members   -  Reputation: 92

Like
0Likes
Like

Posted 09 September 2005 - 12:46 PM

Yet again benchmarking?

Floats are, if used on SSE2 registers, aproximately 2 times faster than Doubles. It might look great, but it would apply only on larger matrices. I would rather have 2x slowdown, than did more often test for rounding errors and played with error cancelation. If you can use double it's not often worthy to play with floats even for slight speed increase. (BTW they are IIRC equally fast on common FPU registers.) One important situation when floats might be neccessary is transfer of prepared data to GFX card. However IIRC there might be problems if exponents would be too large.
Actually there are other situations when float might be of some importance. Div, and sqrt. With these 40 - 80 CPU cycles instructions the half data size might be important. However majority of developers are using

c = 1D/divider
for ... ca[...] = something[...] * c

One operation on high precision number will not kill the above code. Low precision data member might.

As a general rule, if you will work with data that would remain in computer memory use double. If you work with data that needs to be transfered to GFX, and they need to be transfered as a floating point use float (because your GFX card is highly likely is unable to use double, and bandwidth required would kill AGP3.0 / PCIE data transfer)

Also it looks like you'd need some decoupling of your 3D engine, game engine, and world engine.

BTW if anyone would like to play with benchmarking of floats and doubles, try scimark. It has some ability to measure speed differences.

#48 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

0Likes

Posted 09 September 2005 - 01:34 PM

Dividing by a very small double can be just as disastrous as dividing by a very small float. Doubles represent a greater range than floats, but in general it is best to avoid dividing by numbers close to 0, possibly by rewriting the code in a way that avoids the division or checks for values close to 0.

It is similiar to how you never use == to compare two floating point numbers and instead check to see if they are within some epsilon value. If the denominator is very close to 0 it is safer to treat it as if it was 0. If you're dividing by a number that might be 0, don't use == to compare it to 0, use the epsilon test method.

Graphics cards can internally use whatever precision they want, possibly even something different than 32 bit or 64 bit. At certain stages they even tend to use higher precisions to avoid certain artifacts. But for displaying geometry, 32 bit accuracy is plenty.

#49 Shannon Barber   Moderators   -  Reputation: 1390

Like
0Likes
Like

Posted 09 September 2005 - 01:55 PM

Quote:
Original post by Daniel Miller
If you shouldn't use == or !=, then wouldn't > and < be messed up as well?

Yes, but the effect is usually less significant.

e.g.

This may return false:
11.1f / 11.1f == 8.0f / 8.0f


And this could return true:
11.1f / 11.1f < 8.0f / 8.0f


The difference is that there's only 1 value out of 2^32 that make the first one true, however in the second case there's roughly 2^31 values that make it true. So if you're off by 1 bit for ==, it may never return true, whereas if you're off by 1 bit for <, it'll fix itself next iteration. You can have stability problems though if the calculation "lands" on the threshold and thus cause it to iterate true/false/true/true/false/true instead of a clean false/false/false/true/true/true.

Compares on float ought to be "fuzzy" and anything that's within the eplison should be considered equal.


struct scalar
{
typedef float float_t;
scalar() {}
explicit scalar(float_t f) : f(f) {}
float_t f;
//...
};

inline bool operator==(scalar a, scalar b)
{
return abs(b-a).f < std::numeric_limits<scalar::float_t>::epsilon();
}
inline bool operator!=(scalar a, scalar b)
{
return !(a==b);
}
inline bool operator<(scalar a, scalar b)
{
return (a.f<b.f) && (a!=b);
}


#50 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

0Likes

Posted 10 September 2005 - 06:07 AM

Quote:
Original post by Anonymous Poster

Graphics cards can internally use whatever precision they want, possibly even something different than 32 bit or 64 bit. At certain stages they even tend to use higher precisions to avoid certain artifacts. But for displaying geometry, 32 bit accuracy is plenty.


ATI used 24 bits of precision for long time, they didn't delayed switching to 32 bits just for nothing. That 8 bit lower precision caused a some advantage in speed in comparison to pure FP32 bit registers on more advanced cards. Actually majority of registers are 4xFP32, and FP16 has also its place.
32 bits might be plenty if you have environment smaller than 16E6 units, and you never do any multiplication. 32 bit precision might be horrible for scaling and rotation of 3D models. When I used some Bethesda software, I could see theirs geometry precision was by few units smaller, than was neccessary to prevent fall through geometry. ^_^






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS