You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中floor函数与Int转换结果异常,为何未得到预期值49900?

为什么floor(n1)和Int(n1)得到49899而非预期的49900?

这是典型的浮点数精度误差导致的问题,我来一步步帮你理清背后的原因:

核心问题:Float的精度限制

你看到控制台输出n1 : 49900.0,但这只是系统为了可读性做的近似显示——n1的实际值并不是精确的49900.0,而是一个略小于它的数(比如49899.999999999986左右)。

为什么会这样?因为:

  • 4.99是一个十进制小数,但二进制浮点数(Float/Double)无法精确表示所有十进制小数。当你把4.99转换成Float类型时,它会被存储为一个最接近的二进制近似值,这个值本身就略小于4.99。
  • 当你用这个近似值乘以Float(10000)时,误差被放大,最终得到的结果就会略小于49900.0。

验证真实数值

你可以修改代码,用更高精度的格式打印n1,就能看到它的真实面目:

print(String(format: "%.20f", n1))

运行后你会看到类似49899.999999999986030161的输出,这才是n1的实际存储值。

为什么直接调用floor(49900.0)正常?

因为此时的49900.0是一个可以被Float精确表示的数值,所以floor能正确返回49900.0。但你的n1是通过不精确的4.99近似值计算来的,结果自然带误差。

解决方案

根据你的使用场景,有几种可选的解决方式:

  • 改用Double类型:Double的精度是Float的两倍,能大幅降低这类误差。把代码里的Float换成Double,你会发现结果符合预期:
    let n = 4.99/Double(1)
    print("n : \(n)")
    let n1 = Double(10000)*n
    print("n1 : \(n1)")
    let n2 = floor(n1)
    print("n2 : \(n2)")
    let n3 = Int(n1)
    print("n3 : \(n3)")
    
  • 使用Decimal类型:如果是处理货币、金额这类需要精确十进制运算的场景,推荐用Decimal类型,它专门用于精确表示十进制小数:
    let n = Decimal(string: "4.99")! / Decimal(1)
    print("n : \(n)")
    let n1 = Decimal(10000)*n
    print("n1 : \(n1)")
    let n2 = floor(n1)
    print("n2 : \(n2)")
    let n3 = (n1 as NSDecimalNumber).intValue
    print("n3 : \(n3)")
    
  • 添加微小偏移量(谨慎使用):如果必须用Float,可以在调用floor或者转换Int前,给数值加一个极小的偏移(比如0.00001),抵消精度误差:
    let n2 = floor(n1 + 0.00001)
    let n3 = Int(n1 + 0.00001)
    
    注意:这种方法只适用于误差很小的场景,避免在高精度要求的场景使用。

内容的提问来源于stack exchange,提问作者David Goncalves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:48:33