Swift中NumberFormatter为何将19,999,999,999,999,999格式化为20,000,000,000,000,000?
Swift中NumberFormatter格式化大整数出现精度丢失的原因及解决方法
问题原因
这个问题的核心是Double精度限制导致的近似误差:
- Swift的64位Int能容纳的范围(-9223372036854775808 到 9223372036854775807)远大于Double的精确整数范围,Double仅能精确表示2^53以内的整数(约9007199254740992)。
- 当你把超过这个范围的Int转换成NSNumber后,NumberFormatter内部会默认以Double类型解析数值,而Double无法精确存储19999999999999999这类大整数,会自动近似为最接近的可表示值20000000000000000,最终导致格式化结果不符合预期。
解决方案
有两种可靠的解决方式,任选其一即可:
方案一:用NSDecimalNumber避免Double转换
修改格式化函数,使用NSDecimalNumber包装整数,让NumberFormatter以高精度小数模式处理,彻底规避精度丢失:
import Foundation func format(_ num: Int) -> String { let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.groupingSeparator = "," formatter.groupingSize = 3 // 用NSDecimalNumber包装整数,确保高精度处理 let decimalNum = NSDecimalNumber(value: num) return formatter.string(from: decimalNum) ?? String(num) }
方案二:字符串手动添加分隔符
完全绕过NumberFormatter,直接对整数的字符串形式进行处理,手动插入逗号分隔符:
import Foundation func format(_ num: Int) -> String { let numStr = String(num) var formatted = "" let reversedStr = numStr.reversed() for (index, char) in reversedStr.enumerated() { if index != 0 && index % 3 == 0 { formatted += "," } formatted.append(char) } return String(formatted.reversed()) }
内容的提问来源于stack exchange,提问作者Monterey
相关产品推荐
相关产品推荐

