根据 Boaz Stuller 的回答,我为此问题向 Apple 记录了一个错误。在解决这个问题之前,以下是我认为最好的解决方法。这些变通方法仅依赖于将十进制数四舍五入到适当的精度,这是一种可以补充现有代码的简单方法(而不是从格式化程序切换到扫描程序)。
通用编号
本质上,我只是根据对我的情况有意义的规则对数字进行四舍五入。因此,YMMV 取决于您支持的精度。
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[formatter setGeneratesDecimalNumbers:TRUE];
NSString *s = @"0.07";
// Create your desired rounding behavior that is appropriate for your situation
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
NSDecimalNumber *decimalNumber = [formatter numberFromString:s];
NSDecimalNumber *roundedDecimalNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
NSLog([decimalNumber stringValue]); // prints 0.07000000000000001
NSLog([roundedDecimalNumber stringValue]); // prints 0.07
货币
处理货币(这是我试图解决的实际问题)只是处理一般数字的轻微变化。关键是舍入行为的比例由区域设置货币使用的最大小数位数决定。
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[currencyFormatter setGeneratesDecimalNumbers:TRUE];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// Here is the key: use the maximum fractional digits of the currency as the scale
int currencyScale = [currencyFormatter maximumFractionDigits];
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:currencyScale raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
// image s is some locale specific currency string (eg, $0.07 or €0.07)
NSDecimalNumber *decimalNumber = (NSDecimalNumber*)[currencyFormatter numberFromString:s];
NSDecimalNumber *roundedDecimalNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
NSLog([decimalNumber stringValue]); // prints 0.07000000000000001
NSLog([roundedDecimalNumber stringValue]); // prints 0.07