0

I'm using NSNumberFormatter to get the object value of a string currency. No matter what combination of settings I try, I always get weird precision errors.

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle];
[numberFormatter setGeneratesDecimalNumbers:YES];
[numberFormatter setMaximumFractionDigits:2];
[numberFormatter setMinimumFractionDigits:2];
[numberFormatter setRoundingIncrement:@(0.01)];
NSDecimalNumber *value;
[numberFormatter getObjectValue:&value forString:@"$9.95" errorDescription:nil];
NSLog(@"value is %@ class %@", value,[value class]);

Produces:

2014-08-03 19:25:17.640 Test[50776:60b] value is 9.949999999999999 class NSDecimalNumber

It appears that minFractionDigits, maxFractionDigits and roundingIncrement are only relevent in the context of formatting a value to a string, not converting a string to a number. What's even more baffling to me is that NSNumberFormatter is using NSDecimalNumber which is supposed to avoid these types of precision issues.

Am I missing something completely obvious here?

bhirt
  • 266
  • 2
  • 8
  • Did you test, whether the value itself is 9.4999…? Printing out the description probably will use %f, which implies a conversion of the decimal number to a binary fractional number. To check it, simply create an NSDecimalNumber by multiplying value with 100. Thanks @dreamlax – Amin Negm-Awad Aug 04 '14 at 02:00
  • @AminNegm-Awad: The description method more likely uses `NSDecimalString` function to create the output. – dreamlax Aug 04 '14 at 02:01
  • Unfortunately it seems like this is a bug in NSNumberFormatter. Check the duplicate for more info. – dreamlax Aug 04 '14 at 02:02
  • Yes, you are right. I tested it myself and already the production of the NSDecimalNumber instance fails. – Amin Negm-Awad Aug 04 '14 at 02:12

0 Answers0