我遇到意外的行为,使用NSNumberFormatter在ObjC中格式化非常大的数字。
似乎数字格式化器在第15位之后舍入小数(NSDecimalNumber)而不管小数位数。
以下测试在值1,3和5上失败。
两个请求:
如果出现问题,帖子here会列出一个没有足够说明的解决方法。此外,我们的应用程序(银行部门)遍布多个国家/地区,我们将格式链接到后端配置的用户区域设置。这种解决方法意味着我们编写自己的数字格式化程序来处理需求。我不想做的事。
- (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);
}
答案 0 :(得分:4)
不幸的是,NSNumberFormatter
无法与NSDecimalNumber
一起正常使用。
问题(很可能)是它首先要做的就是调用它想要格式化的数字doubleValue
。
另见NSDecimalNumber round long numbers
在使用NSNumberFormatter
多次尝试后,我创建了自己的格式化程序,实际上非常简单:
NaN
。roundToScale:
stringValue
-
.
)[locale objectForKey:NSLocaleDecimalSeparator]
)[locale objectForKey:NSLocaleGroupingSeparator]
)-
或将数字放入括号中。答案 1 :(得分:1)
您应该从这个开源代码编译自己的NSNumberFormatter,更改前缀。这应该允许您调试格式并理解为什么会发生这种情况。最糟糕的情况是,您可以向Apple提交补丁。
答案 2 :(得分:1)
您已将maximumFractionDigits
设置为两个。所有失败的测试都在预期值中有三个小数位。期望或代码需要更改才能匹配。如果我做了这个改变:
formatter.maximumFractionDigits = 3;
然后满足您的所有测试用例。