使用 NSNumberFormatter 生成小数点后尾随零的数字

Posted

技术标签:

【中文标题】使用 NSNumberFormatter 生成小数点后尾随零的数字【英文标题】:Using NSNumberFormatter to generate number with trailing zeros after decimal 【发布时间】: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 以进行第二次转换。也许这有帮助,目前没有时间尝试并写一个答案。 【参考方案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;

【讨论】:

以上是关于使用 NSNumberFormatter 生成小数点后尾随零的数字的主要内容,如果未能解决你的问题,请参考以下文章

NSNumberFormatter 仅四舍五入到小数点后 3 位

NSNumberFormatter 用于 2 个小数位

NSNumberFormatter 适用于小数分隔符但不适用于逗号分隔符

带有数字样式的 NSNumberFormatter NSNumberFormatterCurrencyStyle 逗号问题

在iOS中找出货币中的小数位数

使用 NSNumberFormatter 将数字转换为格式