Swift中如何正确缩减Float数值精度并格式化输出?
问题分析
你的代码核心问题在于reduceScale(to:)方法的逻辑是直接截断小数部分,而非向上取整:
- 对
4.8962965执行reduceScale(to:2)时,乘以100得到489.62965,转成Int直接舍弃小数位变成489,再除以100得到4.89 - 后续
NumberFormatter处理的是已经被截断后的4.89,即便设置了.up的取整模式,也无法得到预期的4.90
解决方法
方法一:直接用NumberFormatter处理原始值(推荐)
系统的NumberFormatter已经集成了取整、本地化、格式控制的所有能力,完全不需要自己写精度缩减逻辑:
extension Float { func formatNumber() -> String { let formatter = NumberFormatter() formatter.usesGroupingSeparator = true formatter.minimumFractionDigits = 2 // 强制显示两位小数,比如4会变成4.00 formatter.maximumFractionDigits = 2 formatter.roundingMode = .up formatter.numberStyle = .decimal formatter.locale = Locale.current // 替换为你的应用自定义locale // 直接传入原始值,让formatter处理所有逻辑 guard let result = formatter.string(from: NSNumber(value: self)) else { return "\(self)" // 兜底处理,避免崩溃 } return result } } // 测试 let value: Float = 4.8962965 let formattedValue = value.formatNumber() // 根据本地化输出4.90或4,90
方法二:修改reduceScale方法实现向上取整
如果必须保留自定义精度处理逻辑,把截断逻辑改成向上取整即可:
extension Float { func reduceScale(to places: Int) -> Float { let multiplier = pow(10, Float(places)) let scaledValue = multiplier * self // 用ceil函数实现向上取整,替代转Int的截断操作 let roundedUp = ceil(scaledValue) return roundedUp / multiplier } func formatNumber() -> String { let num = abs(self) let formatter = NumberFormatter() formatter.usesGroupingSeparator = true formatter.minimumFractionDigits = 2 formatter.maximumFractionDigits = 2 formatter.roundingMode = .up formatter.numberStyle = .decimal formatter.locale = Locale.current // 替换为应用自定义locale let formattedNum = num.reduceScale(to: 2) guard let result = formatter.string(from: NSNumber(value: formattedNum)) else { return "\(formattedNum)" } return result } } // 测试 let value: Float = 4.8962965 let formattedValue = value.formatNumber() // 根据本地化输出4.90或4,90
关键注意点
- 若需要固定显示两位小数(如整数4显示为4.00),必须将
minimumFractionDigits设为2,而非0 - 尽量避免手动处理浮点数值的精度,浮点运算容易出现精度误差,系统
NumberFormatter更可靠 - 永远不要强制解包
formatter.string(from:),添加兜底处理能避免潜在崩溃
内容的提问来源于stack exchange,提问作者I Don't Tell
相关产品推荐
相关产品推荐

