0

I am on macOS, objective-c. Not swift, not iOS.

For passing a float i temporarily need to make it an object at a certain point:

NSNumber* floatNumber = @.5;
// Other stuff ...
float myFloat = [floatNumber floatValue]; // --> (float) 0.5

However, doing the same than above with

NSNumber* floatNumber = @.4;
// Other stuff ...
float myFloat = [floatNumber floatValue]; // --> (float) 0.400000006

This breaks the rest as i require the same float value 0.4

I already tried rounding

floorf([floatNumber floatValue] *100)/100;  // --> (float) 0.400000006

Can someone explain this behaviour and tell me how to solve it

Pat_Morita
  • 3,355
  • 3
  • 25
  • 36

1 Answers1

0

This behavior has to do with floating point error.

By definition, floating-point error cannot be eliminated, and, at best, can only be managed.

https://en.wikipedia.org/wiki/Floating-point_error_mitigation

The error you're seeing has to do with the fact that floating point can only store a limited amount of precision, so after a certain number of places it will begin to look like noise. There was almost certainly some error present in your first example with 0.5, but it was minimal enough that it didn't show up when printed.

One way to improve the situation would be to use double instead of float . On 64-bit architectures (i.e. anything modern,) NSNumber stores floating-point values as double, internally. So if you use doubleValue instead of floatValue, you'll get the higher precision version.

Note that there will still be error, though. It's just the way of floating point. You can store 0.4 in a float or double, but really what that means is "darn close to 0.4". With integer and fixed-point types, there is no error.

TyR
  • 718
  • 4
  • 9