Strange NSNumberFormatter 10_4 behavior with percentages

A bug reported in the recent beta of Billable said users were seeing ‘600.00%’ in the invoices instead of the ‘6.00%’ they expected and were seeing in the rest of the application. A quick review of the code didn’t appear to show any recent changes to the related methods but then I remembered, I did just change all of my programatically created NSNumberFormatters to use a 10_4 behavior. This is also why the other formatters still worked — since even if you do tell Cocoa to use 10_4 behavior, the formatters you create in Interface Builder always use 10_0 behavior.

Lost yet? Read up on the new 10_4 behavior of the formatters on Apple’s site.

Anyways as it turns out there is a bug (or at least, in my opinion, a misunderstanding) in the way a 10_4 NSNumberFormatter turns a ‘6’ into a percent. I’ve created a little application (source) to demonstrate. But the basic of it is… NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease]; [nf setFormat:@”0.00%;0.00%;-0.00%”]; NSLog(@”%@”, [nf stringForObjectValue:[NSDecimalNumber decimalNumberWithString:@”6”]]);

Results in ‘6.00%’.

NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease];
[nf setFormatterBehavior:NSNumberFormatterBehavior10_4];
[nf setFormat:@"0.00%;0.00%;-0.00%"];
NSLog(@"%@", [nf stringForObjectValue:[NSDecimalNumber decimalNumberWithString:@"6"]]);

Results in ‘600.00%’.

rdar://4898265

UPDATE: See comments for more info on why this isn’t a bug. Thanks Peter!

Posted on: December 22, 2006 – 3:20 am

4 Comments

  1. No bug.

    The 10.4 style uses ICU format strings. The ICU documentation says:

    In order to format percentages, create a locale-specific formatter and call the getPercentInstance method. With this formatter, a decimal fraction such as 0.75 is displayed as 75%.

    NSNumberFormatter’s API is a little different (owing to being a subclass of NSFormatter, and having to work like one), but the behavior is still the same. You’ve specified percentages; it sees your 6 as a fraction and renders it as such (6 = 6⁄1 = 600%; 0.75 = 3⁄4 = 75%).

    NSNumberFormatter does let you switch away from this, however. Call [myFormatter setNumberStyle:NSNumberFormatterDecimalStyle]. This is what it gives you when there’s no percent sign in the format; when there is, it gives you NSNumberFormatterPercentStyle.

  2. Thanks for the clarification Peter. Much appreciated.

  3. Andy Lee wrote:

    6.00, 600.00, same thing? :)

  4. As Peter pointed out to me offline, Apple has update their docs with a new section on percentages!

Post a Comment | Comment RSS feed