Swift中Double的舍入:2025年5大最佳实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么在Swift中舍入Double是个痛点(以及如何在2025年与之共存)



每个iOS开发者迟早都会遇到这种情况:需要向用户显示商品价格99.99,但代码中却是99.99000000000001。熟悉吗?欢迎来到Swift中Double舍入的世界——这个话题在Stack Overflow上获得了数千次浏览,即使在2025年也仍然困扰着开发者们。



问题不在于Swift——问题在于浮点数(IEEE 754)本身的特性。Double无法精确表示0.1,就像十进制系统无法精确表示1/3一样。但对用户来说,这不是借口。他们需要屏幕上显示漂亮的数字。



在本文中,我将展示5种经过验证的Swift中Double舍入方法,分析它们的优缺点,并为您提供一个清晰的选择算法。让我们开始吧!



方法1:Foundation — round() + pow(10, n) — 经典方法



最显而易见的方法:将数字乘以10^n,舍入,再除回来。



import Foundation

func roundDouble(_ value: Double, toPlaces places: Int) -> Double { let divisor = pow(10.0, Double(places)) return round(value * divisor) / divisor}

let price = 99.995print(roundDouble(price, toPlaces: 2)) // 100.0 (银行家舍入法)


优点:

  • 简单且可读性强
  • “开箱即用”——无需额外导入


缺点:

  • 精度错误——由于Double的特性,可能得到99.99000000000001而不是99.99
  • 银行家舍入法的问题——round()使用四舍五入,并不总是适用于金融场景
  • pow(10, n) —— 额外的计算开销


此方法适用于UI中的粗略舍入,但不适用于金融计算。



方法2:String(format:) — 通过字符串舍入(UI中最快的方法)



如果您的最终目标是在屏幕上显示数字,为什么还要处理Double?直接将其转换为字符串。



let value = 123.456789let roundedString = String(format: "%.2f", value)print(roundedString) // "123.46"

// 如果需要,再转回Doublelet roundedDouble = Double(roundedString) ?? 0.0


优点:

  • 速度极快——没有多余的数学运算
  • 保证输出正确的小数位数
  • 支持本地化(小数点分隔符)


缺点:

  • 结果是字符串,后续计算需要转换回来(会损失精度)
  • 不适用于银行家舍入法(默认是四舍五入)


非常适合显示价格、百分比、评分——任何精度±0.01不关键的地方。



方法3:NSDecimalNumber — 金融精度的王者



当涉及金钱时,Double是邪恶的。使用NSDecimalNumber——它以十进制格式存储数字,没有舍入误差。



import Foundation

func roundDecimal(_ value: Double, toPlaces places: Int, roundingMode: NSDecimalNumber.RoundingMode = .plain) -> Double { let decimal = NSDecimalNumber(value: value) let handler = NSDecimalNumberHandler( roundingMode: roundingMode, scale: Int16(places), raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false ) return decimal.rounding(accordingToBehavior: handler).doubleValue}

let amount = 99.995print(roundDecimal(amount, toPlaces: 2, roundingMode: .bankers)) // 99.99 (银行家舍入法!)


优点:

  • 完全控制舍入方式—— .plain, .down, .up, .b

博客

书籍推荐