Monday, 22 August 2011

float == float

Never use equality checking with floats, they are not accurate for checking with an equals operator.
For example, this loop would run forever:

for( float a = 0.0f; a != 1.0f; a += 0.1f )

Not ten times. Try it.

This is because 0.1f is an approximation. The IEEE standard float cannot represent 0.1f, only a very near neighbour. In fact, once you've added all ten, the bit pattern is only off by 1 bit, so it's pretty accurate, but still not equal.

1.0f = 0x3f700000
the sum of ten 0.1f is 0x3f700001
quite remarkable that it's so close.

So, you agree, floats are not safe for checking equality, right?

floats are great for equality, but just don't use the wrong ones.
for example, 0.125f has an exact representation in floats, so adding together eight of them will in fact, be perfect.
In fact, floats have exact representations for all the integers right up to 16,777,216.0f, after which the mantissa runs out of accuracy.
so, when you see code like this:

for( float a = 0.0f; a < 100.0f; a += 1.0f )
float percent = a * 0.01f
/* do something with a percent */
if( a == 0.0f || a == 25.0f || a == 50.0f || == 75.0f )
/* something to do with quadrants */

then you can trust it just fine. Seriously. Also, this is useful for times when you might want to not suffer the notorious load-hit-store. If you had done this:

for( int a = 0; a < 100; ++a )
float percent = a*0.1f;
/* do something with a percent */
if( a == 0 || a == 25 || a == 50 || == 75 )
/* something to do with quadrants */

you would be converting from int to float on every run through the loop, which is slow on any modern console.

No comments: