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

使用NSNumberFormatter的.floor roundingMode时,Float与Double计算结果不一致的原因咨询

为啥Float和Double用NumberFormatter.floor会得到不同结果?

嘿,这个问题的根源其实藏在二进制浮点数的精度特性里,咱们一步步理清楚:

1. 浮点数的近似存储问题

十进制里的3.6,在二进制浮点数体系里是没法精确表示的——就像咱们没法用分数精确表示1/3一样。Float(单精度32位)和Double(双精度64位)的存储精度不同,导致它们对36/10的计算结果存储了不同的近似值:

  • Float(36)/Float(10)的实际值是3.5999999046325684,一个略小于3.6的数,误差相对明显。
  • Double(36)/Double(10)的实际值是3.5999999999999996,同样略小于3.6,但误差极小,小到直接打印时Swift都会把它显示成3.6。

2. .floor roundingMode的作用

.floor是向下取整,也就是取不大于原数的最大数值(这里是保留两位小数):

  • 对于Float的近似值(3.5999999...),它比3.6小一丢丢,向下取两位小数时就会被取成3.59。
  • 对于Double的近似值(3.5999999999999996...),因为误差实在太小,NumberFormatter在处理时会把它视为足够接近3.6,向下取整到两位小数就得到了3.60。

3. 怎么避免这种差异?

如果需要精确的十进制计算,建议用Decimal类型代替Float/Double,它专门为十进制数设计,不会有二进制浮点数的精度问题:

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.usesGroupingSeparator = false
formatter.roundingMode = .floor
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2

let v = 36
let scale = 10
let decimalValue = Decimal(v) / Decimal(scale)
let result = formatter.string(from: decimalValue as NSNumber)!
print(result) // 输出 3.60

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:57:39