从特定于语言环境的字符串中获取 NSDecimalNumber? [英] Obtaining an NSDecimalNumber from a locale specific string?

查看:26
本文介绍了从特定于语言环境的字符串中获取 NSDecimalNumber?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些特定于语言环境的字符串 s(例如,0.01 或 0,01).我想将此字符串转换为 NSDecimalNumber.来自 迄今为止我在互联网上看到的示例,这是通过使用 NSNumberFormatter a la 来实现的:

I have some string s that is locale specific (eg, 0.01 or 0,01). I want to convert this string to a NSDecimalNumber. From the examples I've seen thus far on the interwebs, this is accomplished by using an 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 上唯一可用的模式)但向格式化程序表明我想要生成十进制数.请注意,我已经简化了我的示例(我实际上是在处理货币字符串).但是,我显然做错了什么,因为它返回一个说明浮点数不精确的值.

I'm using 10.4 mode (in addition to being recommended per the documentation, it is also the only mode available on the iPhone) but indicating to the formatter that I want to generate decimal numbers. Note that I've simplified my example (I'm actually dealing with currency strings). However, I'm obviously doing something wrong for it to return a value that illustrates the imprecision of floating point numbers.

将特定于语言环境的数字字符串转换为 NSDecimalNumber 的正确方法是什么?

What is the correct method to convert a locale specific number string to an NSDecimalNumber?

请注意,我的示例是为了简单起见.我问的问题也应该与您何时需要获取特定于语言环境的货币字符串并将其转换为 NSDecimalNumber 相关.此外,这可以扩展为特定于语言环境的百分比字符串并将其转换为 NSDecimalNumber.

Note that my example is for simplicity. The question I'm asking also should relate to when you need to take a locale specific currency string and convert it to an NSDecimalNumber. Additionally, this can be expanded to a locale specific percentage string and convert it to a NSDecimalNumber.

推荐答案

根据 Boaz Stuller 的回答,我就这个问题向 Apple 记录了一个错误.在此问题得到解决之前,以下是我认为最好的解决方法.这些解决方法仅依赖于将十进制数四舍五入到适当的精度,这是一种可以补充现有代码的简单方法(而不是从格式化程序切换到扫描程序).

Based on Boaz Stuller's answer, I logged a bug to Apple for this issue. Until that is resolved, here are the workarounds I've decided upon as being the best approach to take. These workarounds simply rely upon rounding the decimal number to the appropriate precision, which is a simple approach that can supplement your existing code (rather than switching from formatters to scanners).

一般数字

基本上,我只是根据对我的情况有意义的规则对数字进行四舍五入.所以,YMMV 取决于您支持的精度.

Essentially, I'm just rounding the number based on rules that make sense for my situation. So, YMMV depending on the precision you support.

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

货币

处理货币(这是我试图解决的实际问题)只是处理一般数字的细微变化.关键是舍入行为的比例由语言环境货币使用的最大小数位数决定.

Handling currencies (which is the actual problem I'm trying to solve) is just a slight variation on handling general numbers. The key is that the scale of the rounding behavior is determined by the maximum fractional digits used by the locale's currency.

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

这篇关于从特定于语言环境的字符串中获取 NSDecimalNumber?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆