Comparing floats, a heads up!
January 11, 2010
When you spend time programming-world-of-higher-abstraction (Ruby & Python) and then move to a lower level, in this case Objective-C, mistakes are bound to happen. Let me share with you guys one of mine…
It was a sunny friday afternoon, I was trying to fix a glitch in my animation path. To my own happy surprise I discovered that it was fairly simple to plug this hole. All I needed was a special case when a parameter reached angle 0.00000, so of I went with some duck tape and glue (pronounced if-statements) looking something like:
if(curveAmplitude == 0.0f){
//dragon-code
}
To my total surprise the if-statement never turned out to be true. After using my favorite method for discovering how stuff works, trial-and-error, I remembered something about floats & doubles not being reliable. I started reading over the IEEE standard and David Goldberg’s paper “What Every Computer Scientist Should Know About Floating-Point Arithmetic”. As Mr. Goldberg states it all boils down to this:
“Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. […] the results of a floating-point calculation must often be rounded in order to fit back into its finite representation. The rounding error is the characteristic feature of floating-point computation.”
Thank you Mr. Goldberg for that! Now that the problem is identified it is time for a solution.
Solution:
Add two minimal macros to your source, these macros compares your number to epsilon which is the smallest float available to the system.
#define fEqual(a,b) (fabs((a) - (b)) < FLT_EPSILON)
#define fEqualToZero(a) (fabs(a) < FLT_EPSILON)
Note that if you are into precision this will not get you all the way. There rounding problem is still there, but in most simple cases this is a good-enough-solution.
sinf() & cosf() – Don’t forget about the radians!
December 9, 2009
So little time and so much to code (and even less time for writing blog posts =).
Recently I have submerged myself in the world of Core Animation. Apple has done a great job with this framework. For someone who is graphically challenged this has been a steep uphill battle. One mine I stepped on, was that all the core C math functions really prefer radians over degrees. I wrote the following two helper methods to do this conversion:
- (CGFloat)_degreesToRadians:(CGFloat)degrees{ return degrees * (M_PI / 180); } - (CGFloat)_radiansToDegrees:(CGFloat)radians{ return radians * (180 / M_PI); }