我有一些特定于语言环境的字符串(例如,0.01或0,01).我想将此字符串转换为NSDecimalNumber.从我迄今为止在网站上看到的例子来看,这是通过使用NSNumberFormatter a la来实现的:
NSString *s = @"0.07"; NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; [formatter setGeneratesDecimalNumbers:YES]; NSDecimalNumber *decimalNumber = [formatter numberFromString:s]; NSLog([decimalNumber stringValue]); // prints 0.07000000000000001
我正在使用10.4模式(除了根据文档推荐,它也是iPhone上唯一可用的模式),但向格式化程序指示我想生成十进制数字.请注意,我已经简化了我的示例(我实际上正在处理货币字符串).但是,我显然做错了,它返回一个值,说明浮点数的不精确.
将特定于语言环境的特定数字字符串转换为NSDecimalNumber的正确方法是什么?
编辑:请注意,我的例子是为了简单起见.我问的问题也应该与何时需要获取特定于语言环境的货币字符串并将其转换为NSDecimalNumber有关.此外,这可以扩展为特定于语言环境的百分比字符串,并将其转换为NSDecimalNumber.
多年后:
+(NSDecimalNumber *)decimalNumberWithString:(NSString *)numericString
在NSDecimalNumber
.
根据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