I am running into unexpected behaviour formatting very large numbers in ObjC using the NSNumberFormatter.
It seems that the number formatter rounds decimals (NSDecimalNumber) after the fifteenth digit regardless of fraction digits.
The below test fails on values 1,3 and 5.
Two requests:
- Any suggestions on alternative code would be greatly appreciated?
- I assume the issue is happening due to the usage of a hard-coded digit limit in NSNumberFormatter?
The post here lists a workaround without sufficient description if the problem. Also our application (banking sector) runs across multiple countries and we link the formatting to the user's locale as configured in the backend. This workaround would imply that we write our own number formatter to handle the requirement. Something I do not want to do.
- (void)testFormatterUsingOnlySDK {
NSDecimalNumber *value1 = [NSDecimalNumber decimalNumberWithMantissa: 9423372036854775808u exponent:-3 isNegative:YES];
NSDecimalNumber *value2 = [NSDecimalNumber decimalNumberWithMantissa: 9999999999999990u exponent:-3 isNegative:YES];
NSDecimalNumber *value3 = [NSDecimalNumber decimalNumberWithMantissa: 9999999999999991u exponent:-3 isNegative:YES];
NSDecimalNumber *value4 = [NSDecimalNumber decimalNumberWithMantissa: 99999999999999900u exponent:-4 isNegative:YES];
NSDecimalNumber *value5 = [NSDecimalNumber decimalNumberWithMantissa: 11111111111111110u exponent:-4 isNegative:YES];
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
formatter.allowsFloats = YES;
formatter.maximumFractionDigits = 3;
[self assertStringAreEqualWithActual:[formatter stringFromNumber:value1] andExpeted: @"-9423372036854775.808"];
[self assertStringAreEqualWithActual:[formatter stringFromNumber:value2] andExpeted: @"-9999999999999.99"];
[self assertStringAreEqualWithActual:[formatter stringFromNumber:value3] andExpeted: @"-9999999999999.991"];
[self assertStringAreEqualWithActual:[formatter stringFromNumber:value4] andExpeted: @"-9999999999999.99"];
[self assertStringAreEqualWithActual:[formatter stringFromNumber:value5] andExpeted: @"-1111111111111.111"];
}
- (void)assertStringAreEqualWithActual:(NSString *)actual andExpeted:(NSString *)expected {
STAssertTrue([expected isEqualToString:actual], @"Expected %@ but got %@", expected, actual);
}