繁体   English   中英

在 Swift 中使用 NumberFormatter 进行大十进制数格式化

[英]Large decimal number formatting using NumberFormatter in Swift

我这样做是为了格式化数字,但它对大数字失败

let formatter = NumberFormatter()
formatter.numberStyle = .decimal


    if let number = formatter.number(from: "123456789123456789123") , let str = formatter.string(from:number){

        print(number)
        print(str)
    }

它打印

123456789123456800000
123,456,789,123,456,800,000

它应该打印

123456789123456789123
123,456,789,123,456,789,123

我认为应该是数字溢出,有没有其他方法可以实现这种事情。

这个问题的根源是三方面的:

  • 从版本 5.6 开始,Swift 不支持十进制文字。
  • Decimal() 支持最多 38 位精度。
  • Double() 支持大约 17 位精度。

因此,当使用 Decimals 表示精度超过 17 位的数字时,千万不要做任何会将 Decimal 的值转换为 Double 的事情。 这包括用文字初始化:

print (Decimal(1234567890.12345678901234567890)) 
// 1234567890.1234569216
print (Decimal(string: "1234567890.12345678901234567890")!) 
// 1234567890.12345678901234567890

Decimal(1234567890.12345678901234567890) 产生值 1234567890.1234569216 因为 1234567890.12345678901234567890 是一个 Double 文字,精度限制为大约 17 位数字。

遗憾的是,NumberFormatter 显然从未收到有关此问题的备忘录。

var dec = Decimal(string: "1234567890.12345678901234567890")!
let f = NumberFormatter()
f.numberStyle = .decimal
f.minimumFractionDigits = 20
print (f.string(from: dec as NSDecimalNumber)!) // 1,234,567,890.12346000000000000000

所以目前,没有办法让 Swift 准确地产生精度超过 17 位的本地化十进制数字。 例如,NumberFormatter 无法生成字符串 1,234,567,890.12345678901234567890,即使 Decimal 可以表示该精确值。

您可以使用 String(describing:)

print (String(describing:(Decimal(string: "1234567890.12345678901234567890")!)))
// 1234567890.1234567890123456789

对于我自己的一个应用程序,我制作了一个“穷人的”小数格式器,它使用所需区域设置中的小数点分隔符简单地输出完整值:

let locale = Locale(identifier: "fr_FR")
dec = Decimal(string: "1234567890,12345678901234567890", locale: locale)!

let formatter = NumberFormatter()
formatter.locale = locale
let localizedSeparator = String(formatter.decimalSeparator.first ?? ".")

let fractionDigits = 20
var strings = String(describing:(dec)).split(separator: (Locale.current.decimalSeparator?.first) ?? "." )
var result = strings[0]
if fractionDigits > 0 {
    if strings.count > 1 {
        while strings[1].count < fractionDigits { strings[1] += "0" }
        result += localizedSeparator + String(strings[1].prefix(fractionDigits))
    }
    else {
        result += localizedSeparator + (0..<fractionDigits).map{_ in "0"}
    }
}

print (result) // 1234567890,12345678901234567890

您可以显式创建一个Decimal来解决提到的错误

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
if let decimalNumber = Decimal(string: "123456789123456789123"), let str = formatter.string(from:decimalNumber as NSNumber) {
    print(decimalNumber)
    print(str)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM