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

Smalltalk中rounded函数原理及千分位舍入异常问题咨询

Smalltalk中rounded函数原理及千分位舍入问题解析

一、rounded函数的工作原理

rounded方法用于将数值四舍五入到最近的整数,核心实现逻辑如下:

rounded
  "Answer an Integer nearest to receiver"
  ^(self + (self sign * 0.5)) truncated

具体执行步骤:

  1. 通过self sign获取当前数值的符号:正数返回1,负数返回-1,0返回0
  2. 用符号值乘以0.5,得到与原数同符号的偏移量(0.5或-0.5)
  3. 将原数加上该偏移量后,调用truncated方法截断小数部分(向零取整),最终得到最接近原数的整数

示例:

  • 正数1.4:1.4 + 0.5 = 1.9,truncated后得到1
  • 正数1.6:1.6 + 0.5 = 2.1,truncated后得到2
  • 负数-1.4:-1.4 + (-0.5) = -1.9,truncated后得到-1
  • 负数-1.6:-1.6 + (-0.5) = -2.1,truncated后得到-2

二、将小数舍入到千分位(3位小数)的方法

常规实现方式

先将数值放大1000倍,调用rounded取整后再缩小1000倍:

roundedToThreeDecimals
  ^(self * 1000) rounded / 1000

若环境支持,也可直接使用roundTo:方法指定精度:

self roundTo: 0.001

三、测试异常情况分析

相关代码片段

调用者方法

cbPrintPercentageString
   ^AbtpercentageConverter new
    primObjectToPrint: self

被调用者方法

primObjectToPrint: anInput 
   ^(super primObjectToPrint: anInput*100), '%'

测试案例

  • 输入1:anInput: 0.014545(Float类型)
    计算:0.014545 * 100 = 1.4545,舍入到3位小数后输出1.455%,符合预期
  • 输入2:anInput: 0.018045(Float类型)
    计算:0.018045 * 100 = 1.8045,预期舍入结果为1.805%,但实际输出1.804%

异常原因

问题源于Float类型的精度限制:十进制小数0.018045无法被二进制浮点数精确表示,实际存储的数值略小于理论值1.8045(如1.804499999999999...),舍入时被判定为小于1.8045,最终得到1.804。

解决方法

  1. 改用Decimal类型:Decimal可精确表示十进制小数,避免二进制浮点数的精度误差
  2. 精度修正:若必须使用Float,可在舍入前添加极小偏移量(如1e-8)修正精度,但需谨慎使用,避免引入新误差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:00:48