Comparing two equal CGFloat:s, getting positive (YES) result

Jonny picture Jonny · May 23, 2013 · Viewed 9.5k times · Source

Until now this has not been a problem but from about today I ran into a strange issue that does not happen all the time, but rarely, I'd say one time out of 50, or even less.

I'm comparing two CGFloat:s like this:

const CGFloat MYFIRSTFLOAT = /* get the first value */
const CGFloat THESECONDFLOAT = /* get the second value */
if (MYFIRSTFLOAT < THESECONDFLOAT) {
// do something
}
else {
// Do something else
}

As you can see I'm not comparing using == or anything because these are floats... (like, it shouldn't be related to How dangerous is it to compare floating point values? now should it)

And the problem I'm having is I run into the occasion where the two values are exact, but the comparison evaluates to YES. In my case both of the values are "8926.5" - this value I got from LLDB. Is there a good explanation to this??? (I'm thinking that LLDB rounds off both values, meaning that they could be other values really - but why then would this also happen at runtime?)

This kind of puts me off cause I can't just see the problem... well, I'm thinking of forcing the floats to int only for this comparison, and it might be ok for my use this time, but I feel that this problem had better be totally understood :-P

Answer

Midhun MP picture Midhun MP · May 23, 2013

Try this:

const CGFloat a = 8926.5;
const CGFloat b = 8926.5;
if (a<b)
{
    NSLog(@"Yes");
}
else
{
    NSLog(@"No");
}

This will print No.

Now change the value like

const CGFloat a = 8926.5;
const CGFloat b = 8926.50007;

This will print Yes. But if you print these values using LLDB or po statement both will display 8926.5 . So issue is with the values, and LLDB wraps the value. That's why the issue happens.

Suggestion:

Change the if condition like:

if(fabsf(MYFIRSTFLOAT)<fabsf(THESECONDFLOAT))
{
  //Do something
}