1
NSLocale *locale = [NSLocale currentLocale];
NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init];
[currencyStyle setLocale:locale];
[currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyStyle setFormatterBehavior:NSNumberFormatterBehavior10_4];
[currencyStyle setCurrencySymbol:[countriesCurrency objectForKey:currency]];
[currencyStyle setRoundingIncrement:[NSNumber numberWithFloat:0.01]];

Since 2012 code like below returned "0.70 €" and that was great as it's exactly what is expected.

po [currencyStyle stringFromNumber:[NSNumber numberWithFloat:0.70]]

BUT since iOS 13 (app build with xCode 10.3, just users with iOS 13 on their iPhones installed app from the AppStore. Same for build throw xCode 11 on iOS 13.0 and 13.1 beta) exactly same code returns "0,69999998435378074 €"

After quick midnight investigations found that if add

currencyStyle.usesSignificantDigits = YES;

then result will be "0.7 €" - much better but still not exactly what was expected ("0.70 €").

Any ideas how to make setRoundingIncrement great again?

[UPDATE]: Rewriting the same code to swift solve the problem but this sounds like temp solution in the case all the rest app is in Obj-C.

Yauheni Shauchenka
  • 753
  • 1
  • 9
  • 26
  • To be honest, I am not sure what exactly is rounding increment because the documentation says nothing about it. Are you sure. Wouldn't it be enough to set `minimumFractionDigits = 2` and `maximumFractionDigits = 2`? – Sulthan Sep 21 '19 at 07:13
  • @Sulthan just tried - same result – Yauheni Shauchenka Sep 21 '19 at 14:35
  • @Sulthan You should not set the fraction digits for a currency formatter. Not all currencies use the same number of digits. – rmaddy Sep 21 '19 at 15:31
  • @YauheniShauchenka You failed setting `.minimumFractionDigits` *without* setting `.roundingIncrement`? However, using floating point numbers for currencies is wrong by design. Using float as floating pointer numbers for currencies is wronger by design. At least try it with doubles. – Amin Negm-Awad Sep 23 '19 at 14:37
  • @AminNegm-Awad by the way we just tried and faced the same code written in swift working well. Float is not an issue here as we do need just 2 digits after comma, that is price. – Yauheni Shauchenka Sep 23 '19 at 15:19
  • Swift might encode this as double. In C floating point literals are double, too. But you force the compiler to convert it to a float by using `-numberWithFloat:`. You might not force the Swift compiler. *Float is not an issue here as we do need just 2 digits after comma, that is price.* Before you continue using floating pint numbers, you should really, really, really get informed how floating point numbers work, This statement is highly erroneous: Standard Floating point numbers store fractions in binary values (0.5, 0.25, …) You have 2 digit of *decimal* fractions. This does not always map. – Amin Negm-Awad Sep 23 '19 at 21:15
  • What do you think, why `NSDecimal` exists? – Amin Negm-Awad Sep 23 '19 at 21:20
  • Just tested it. `0.7` isn't storable in `float` and `double`: `(lldb) p 0.7 (double) $6 = 0.69999999999999996 (lldb) p 0.7f (float) $7 = 0.699999988` – Amin Negm-Awad Sep 23 '19 at 21:23

0 Answers0