Reputation: 1245
In my application I am using an external API which communicates using json. Today I encountered strange (it may be strange just due to my inexperience in iOS) behavior between floats and NSNumbers. The thing is that I am receiving a float in APIs response, in this particular case it is 135.99. When native obj-c json parser parse the response it creates NSNumber with that value. It works perfect. But at when I started using this API I didn't know how native json parser bahaves, so I've been doing something like this:
NSNumber * number = [NSNumber numberWithFloat:[[response objectForKey:@"Number"] floatValue]];
So, what is happening above is actually casting NSNumber to float and creating new NSNumber with that float. And what is so strange about it? Strange (for me) is that above line generates NSNumber with value... 135.99001 instead of 135.99 which is the proper one.
I know that float arithmetics is really messed up, especially in languages like PHP (0.2 + 0.7 not equals 0.9), but I haven't expected that in languages like objective-c, which is a superset od C language, I would find such mess to. Does anyone has a good explanation to that issue?
Upvotes: 4
Views: 1078
Reputation: 52538
You are making one beginners mistake, and that is assuming that "float" is the correct type for floating point numbers. It's not. Unless you have a really good reason to use float, "double" is the type that you should be using. JSON parsers will inevitably use [NSNumber numberWithDouble:...] to create the NSNumber objects they store (or [NSNumber numberWithLongLong:...] or NSDecimalNumber), but never [NSNumber numberWithFloat:].
float has very limited precision compared to double. You can be sure that in most cases, [NSNumber numberWithFloat:...] will give you different results because of the limited precision.
Upvotes: 2
Reputation: 18253
For languages like C (and I suspect PHP, too) float (and double) arithmetics are not really tied to the language, but to the underlying hardware.
For modern computers that means IEEE floating point arithmetic as implemented by the CPU, so you'd get the same problems if you wrote your program in C, Pascal, FORTRAN, etc. They all just call the CPU's floating point instructions and leave it at that.
Upvotes: 0
Reputation: 14068
Odd things happen with floats. It is part of their nature that they are inprecize.
Besides that I do not fully understand why you are converting (not just type casting) your nice NSNumber into float just to create a new NSNumber object out of the float, you should never ever expect two float values to be equal even if you cannot think of any reason why they should be different.
Which means, when ever it comes to comparing floats, you should never ever compare float1 == float2
. Better compare abs(float1-float2) < 0.001
or what ever significance is of importance.
Some general about these behaviour of floats are well explained on this site: http://floating-point-gui.de/
Upvotes: -1