Ubuntu 22.04下NumberFormatter格式化Float小数位数异常求助
Float值在Linux下NumberFormatter格式化异常的解决办法
需要将数值始终保留逗号后2位小数,但部分Float值在Linux(Ubuntu 22.04)环境下无法通过NumberFormatter正确格式化,macOS 14.7下运行正常。
代码示例
import Foundation let floatNumber: Float = 17889.055 let roundedNumber: Float = (floatNumber * 100).rounded() / 100 let formatter: NumberFormatter = NumberFormatter() formatter.locale = Locale(identifier: "de_DE") formatter.numberStyle = .decimal formatter.maximumFractionDigits = 2 formatter.minimumFractionDigits = 2 formatter.groupingSeparator = "." formatter.decimalSeparator = "," print(formatter.string(from: NSNumber(value: floatNumber)) ?? String(format: "%.2f", floatNumber)) print(formatter.string(from: NSNumber(value: roundedNumber)) ?? String(format: "%.2f", roundedNumber))
实际输出(Linux)
swift test.swift 17.889,055 17.889,061
预期输出
swift test.swift 17.889,06 17.889,06
macOS下输出
17.889,05 17.889,06
解决办法
方案1:改用Double类型
Float是单精度浮点型,无法精确存储17889.055这类十进制小数,实际存储值存在微小误差。Linux下Foundation对该误差的处理逻辑和macOS不同,导致格式化结果异常。改用双精度的Double能大幅降低精度偏差:
import Foundation let doubleNumber: Double = 17889.055 let roundedDouble: Double = (doubleNumber * 100).rounded() / 100 let formatter: NumberFormatter = NumberFormatter() formatter.locale = Locale(identifier: "de_DE") formatter.numberStyle = .decimal formatter.maximumFractionDigits = 2 formatter.minimumFractionDigits = 2 formatter.groupingSeparator = "." formatter.decimalSeparator = "," print(formatter.string(from: NSNumber(value: doubleNumber)) ?? String(format: "%.2f", doubleNumber)) print(formatter.string(from: NSNumber(value: roundedDouble)) ?? String(format: "%.2f", roundedDouble))
方案2:使用Decimal类型精确处理
Decimal专为十进制精确运算设计,完全避免浮点精度丢失问题,是处理货币、精确小数场景的最优选择:
import Foundation let decimalNumber = Decimal(string: "17889.055")! let roundedDecimal = decimalNumber.rounding(accordingTo: .init(scale: 2, roundingMode: .plain)) let formatter: NumberFormatter = NumberFormatter() formatter.locale = Locale(identifier: "de_DE") formatter.numberStyle = .decimal formatter.maximumFractionDigits = 2 formatter.minimumFractionDigits = 2 formatter.groupingSeparator = "." formatter.decimalSeparator = "," print(formatter.string(from: roundedDecimal as NSNumber) ?? "\(roundedDecimal)")
原因总结
- Float的单精度存储特性导致无法精确表示部分十进制小数,存储值存在误差;
- Linux与macOS的Foundation框架对浮点误差的格式化处理逻辑存在差异,引发输出异常;
- Double提升精度减少误差,Decimal则从根源上解决精度问题。
内容的提问来源于stack exchange,提问作者lain
相关产品推荐
相关产品推荐

