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

NSDecimalRound向下舍入Decimal值出现非预期结果的原因咨询

问题根因

这个异常和NSDecimalRound的舍入逻辑没有关系,问题出在你初始化Decimal的方式上。

  • 你代码里写的2341.2142、2341.2146这类小数字面量,会先被编译器解析为Double类型的二进制浮点数。而二进制浮点数本身就无法精确表示绝大多数十进制小数,实际存储的是和目标值有微小偏差的近似值:
    • 字面量2341.2142对应的Double实际值约为2341.2141999999998,比真实的2341.2142略小
    • 字面量2341.2146对应的Double实际值约为2341.2145999999997,同样比真实值略小
  • 当你把这个已经带误差的Double值赋值给Decimal变量时,Decimal会精确存储这个有偏差的数值。此时调用NSDecimalRound选择.down(向下舍入,即向负无穷方向取不大于原值的最大符合精度值),自然会得到比你预期小0.0001的结果。
  • 第一个例子里2341.2143看起来结果正常,只是因为这个值对应的Double近似值刚好略大于真实值,向下舍入4位时刚好和你的预期一致,完全是巧合。
正确写法

要避免这个问题,核心是不要经过Double类型中转来初始化Decimal,从根源上切断二进制浮点数的精度误差传递:

  • 优先使用字符串初始化Decimal,可以保证十进制值完全精确:
var unrounded: Decimal = Decimal(string: "2341.2142")!
var rounded = Decimal()
NSDecimalRound(&rounded, &unrounded, 4, .down)
print(rounded) // 输出2341.2142,符合预期
  • 如果需要做数值计算,全程使用Decimal的运算方法,不要先用Double完成计算再转成Decimal做舍入。

只要你使用var x: Decimal = 2341.2142这种直接赋值浮点数字面量的写法,编译器就会自动先完成Double类型的解析,精度误差就有可能被引入,和后续的舍入操作无关。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:21:36