TrevorPeyton
TrevorPeyton

Reputation: 669

Objective C if statement possibly not working correctly

I am very hesitant to put this because I know that 99.9% of the time the user is to blame for an error but I am seriously confused about this one.

I have a float named rotation defined in my header as such:

@property(nonatomic)float rotation;

After the rotation has been given a value I check it using this if statement

if (fabsf(rotation) == M_PI_2)
{
    NSLog(@"Execute more code now");
}

Now I have checked the definition of M_PI_2 and came up with 1.57079632679489661923132169163975144

I noticed that it wasn't working so I put another NSLog before the if statement as such:

    NSLog(@"%f == %f", fabs(rotation), M_PI_2);

These were the results I got:

2014-06-26 16:29:40.831 76J284E[82085:60b] 0.000000 == 1.570796
2014-06-26 16:29:40.834 76J284E[82085:60b] 3.141593 == 1.570796
2014-06-26 16:29:44.653 76J284E[82085:60b] 0.000000 == 1.570796
2014-06-26 16:29:44.658 76J284E[82085:60b] 3.141593 == 1.570796
2014-06-26 16:29:47.951 76J284E[82085:60b] 0.000000 == 1.570796
2014-06-26 16:29:47.953 76J284E[82085:60b] 3.141593 == 1.570796
2014-06-26 16:29:54.305 76J284E[82085:60b] 0.000000 == 1.570796
2014-06-26 16:29:54.310 76J284E[82085:60b] 1.570796 == 1.570796
2014-06-26 16:29:54.313 76J284E[82085:60b] 4.712389 == 1.570796
2014-06-26 16:29:54.318 76J284E[82085:60b] 3.141593 == 1.570796

Shouldn't a few of those trigger the if statement? What am I doing wrong here, thanks.

Edit

I should add that I am defining rotation with M_PI_2 (At certain times)

Upvotes: 0

Views: 79

Answers (3)

Bruce Dawson
Bruce Dawson

Reputation: 3502

Your problem is that M_PI_2 is a double and rotation is a float. This statement:

float rotation = M_PI_2;

takes the double-precision constant M_PI_2, rounds it to float precision (throwing away 29 bits of mantissa) and then assigns it to rotation.

Later on you check to see if the rounded value matches the unrounded value. It doesn't. 'cause it's been rounded.

try defining M_PI_2 1.570796

Nope. 1.570796 is still a double, and cannot be exactly represented by a float or a double, so the rounding issue still occurs. Try this:

const float M_PI_2 = 1.57079632679489661923132169163975144f;

float rotation = M_PI_2;

if (rotation == M_PI_2) ...

Assigning the constant to a float and/or appending 'f' to the constant will do the trick.

For more details:

http://randomascii.wordpress.com/2012/06/26/doubles-are-not-floats-so-dont-compare-them/

Also, when printing floats you need to print nine digits of mantissa, otherwise you don't know what float you have. For doubles you need 17 digits of mantissa. For more information:

http://randomascii.wordpress.com/2012/03/08/float-precisionfrom-zero-to-100-digits-2/

Upvotes: 2

Brandon
Brandon

Reputation: 2427

There are two problems. You defined M_PI_2 to be 1.57079632679489661923132169163975144 and your trying to see if it's equal to 1.570796. It's almost equal but not quite. If those numbers were how many trillions of dollars I have in my account, I'd prefer them to not be equal and to take the M_PI_2 one.

Second you can't directly compare floating point numbers due to floating point calculation errors. Heres a good discussion on the problem How dangerous is it to compare floating point values?

Upvotes: 1

onit
onit

Reputation: 6376

The numbers are not equal, you just aren't printing the complete value of the floating point number. This article talks about C++, but the same principles apply.

Upvotes: 2

Related Questions