【问题标题】:Using NSNumberFormatter to generate number with trailing zeros after decimal使用 NSNumberFormatter 生成小数点后尾随零的数字
【发布时间】:2014-10-28 05:57:44
【问题描述】:

在 Swift 中,您将如何创建一个 NSNumberFormatter 来保留小数点 (12.000) 后的尾随零,同时生成适合当前语言环境的数字?

我当前的代码和示例输出:

let formatter = NSNumberFormatter()
formatter.numberStyle = .DecimalStyle
formatter.locale = NSLocale.currentLocale()
formatter.maximumFractionDigits = 10

var doubleNumString = "12.0"
println(formatter.numberFromString(doubleNumString)) //in English it prints 12, want it to print 12.0

var doubleNumString = "12.000"
println(formatter.numberFromString(doubleNumString)) //prints 12, want it to print 12.000

var doubleNumString = "12.125"
println(formatter.numberFromString(doubleNumString)) //prints 12.125 as expected

var doubleNumString = "1234"
println(formatter.numberFromString(doubleNumString)) //prints 1,234 as expected

我已经对其进行了编码,如果字符串以小数 ("12.") 结尾,则它不会使用此格式化程序来生成数字,而是只显示数字,然后显示小数(但我需要改善这一点,因为某些语言从右到左阅读)。

一种解决方案是检查字符串是否包含句点,如果是,则检查其后面的所有数字是否为 0,如果是,则不要通过数字格式化程序运行它,而是只运行 int 值通过格式化程序然后附加/前置小数点后跟适当数量的 0。

有更好/更清洁的解决方案吗?

【问题讨论】:

  • 一个 number 没有尾随零,只有它的 string 表示。 "12.0" 和 "12.000" 转换为 数字 给出完全相同的结果,并且无法将它们区分为数字。 – 为什么不能只使用字符串本身?
  • @Martin 因为字符串始终为英文格式,并且输出数字需要遵守当前的语言环境,但如果字符串中存在尾随零,则还要保留它们。
  • 然后您可以转换字符串->数字->字符串,但您必须计算尾随零的数量并将其设置为 minimum+maximumFractionDigits 以进行第二次转换。也许这有帮助,目前没有时间尝试并写一个答案。

标签: ios swift double nsnumberformatter nslocale


【解决方案1】:

正如 Martin R 所提到的,您可以将 minimumFractionDigitsmaximumFractionDigits 设置为相同的数字,这将强制始终显示许多小数位数。要知道要显示多少,您需要在小数点后取一个子字符串到末尾并计算其元素。为了知道是否所有小数位都是 0,我创建了一个辅助方法,该方法将该子字符串转换为一个数字,如果它等于 0,那么你就知道它们都是 0。

不幸的是,您需要根据原始字符串编号使用几个不同的NSNumberFormatters 将字符串转换为本地化编号。因此,如果它确实包含小数,并且它之后的所有内容都是 0,那么您需要创建一个不同的格式化程序,将字符串转换为数字,然后将该数字转换为字符串,以便根据用户的语言环境显示它。否则,您可以使用原始数字格式化程序。

【讨论】:

    【解决方案2】:

    此功能可满足您的要求。从语言环境(例如 en_US)传递相同的 &

    + (NSString*) stringForString:(NSString*) string forLocale:(NSString*) toLocaleCode fromLocal:(NSString*) fromLocaleCode {
    
        NSLocale *fromLocale = [[NSLocale alloc] initWithLocaleIdentifier:fromLocaleCode];
        NSNumberFormatter *sourceFormatter = [[NSNumberFormatter alloc] init];
        [sourceFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
        [sourceFormatter setUsesGroupingSeparator:NO];
        [sourceFormatter setLocale:fromLocale];
        NSNumber *localizedNumber = [sourceFormatter numberFromString:string];
    
        if (!localizedNumber) {
            return string;
        }
    
        NSLocale *toLocale = [[NSLocale alloc] initWithLocaleIdentifier:toLocaleCode];
    
        NSNumberFormatter *destinationFormatter  = [[NSNumberFormatter alloc] init];
        [destinationFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
        [destinationFormatter setUsesGroupingSeparator:NO];
        [destinationFormatter setLocale:toLocale];
        NSString *localizedString = [destinationFormatter stringFromNumber:localizedNumber];
    
        //add the zeros which were dropped because of the sourceDecimalString number conversion e.g. 0.20 is converted to 0.2
    
        if (localizedString.length < string.length) {
            NSRange rangeOfDecimal = [string rangeOfString:sourceFormatter.decimalSeparator];
            if (rangeOfDecimal.location != NSNotFound) {
                NSString* sourceDecimalString = [string substringFromIndex:rangeOfDecimal.location];
    
    
                rangeOfDecimal = [localizedString rangeOfString:destinationFormatter.decimalSeparator];
                if (rangeOfDecimal.location != NSNotFound) {
                    NSString* destinationDecimalString = [localizedString substringFromIndex:rangeOfDecimal.location];
    
                    if (destinationDecimalString.length <  sourceDecimalString.length) {
                        int difference = sourceDecimalString.length - destinationDecimalString.length;
                        int toalDecimalDigits = (destinationDecimalString.length - 1) + difference; //-1 to remove '.'
    
                        destinationFormatter.minimumFractionDigits = toalDecimalDigits;
                        destinationFormatter.maximumFractionDigits = toalDecimalDigits;
    
                        localizedString = [destinationFormatter stringFromNumber:localizedNumber];
                    }
                }
                else{//this indicates no decimal separator in the return string
                    int toalDecimalDigits = (sourceDecimalString.length - 1); //-1 to remove '.'
    
                    destinationFormatter.minimumFractionDigits = toalDecimalDigits;
                    destinationFormatter.maximumFractionDigits = toalDecimalDigits;
    
                    localizedString = [destinationFormatter stringFromNumber:localizedNumber];
                }
    
            }
        }
    
        return localizedString;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多