
在 Go 中直接 int(f * 1000) 会因浮点数精度丢失导致结果错误(如得 1002 而非 1003),正确做法是先加 0.5(正数)或减 0.5(负数)再截断,实现就近舍入到整数。
在 go 中直接 `int(f * 1000)` 会因浮点数精度丢失导致结果错误(如得 1002 而非 1003),正确做法是先加 0.5(正数)或减 0.5(负数)再截断,实现就近舍入到整数。
Go 的浮点数到整数转换遵循向零截断(truncation toward zero)规则:int(1002.999) 得 1002,int(-1002.999) 得 -1002。这与四舍五入不同,因此当 float64 因二进制表示限制而略小于理论值(如 1.003 实际存储为 1.0029999999999999)时,f * 1000 可能为 1002.999...,截断后即为 1002 —— 这正是问题根源。
✅ 正确方案:使用“偏移 + 截断”实现就近舍入
对非负数,添加 0.5 后截断即可完成四舍五入:
f := 1.003 result := int(f*1000 + 0.5) // → 1003
但该策略对负数不适用。例如 f = -1.003 时:
- f * 1000 ≈ -1002.999
- -1002.999 + 0.5 = -1002.499 → int() 截断得 -1002(错误,期望 -1003)
因此需区分符号处理。推荐封装为健壮的辅助函数:
func roundToInt(f float64) int {
if f <h3>⚠️ 注意事项</h3>
- 乘数需明确:roundToInt(f * 1000) 中的 1000 表示保留三位小数;若需两位小数(如金额),应乘 100。
- 溢出风险:float64 范围大,但 int(通常为 int64)有上限(±9,223,372,036,854,775,807)。对极大数值,建议先检查 math.IsInf 或用 int64 显式声明。
- 零值安全:roundToInt(0.0) 返回 0,逻辑正确。
- 不依赖标准库:该方法纯语言原生,无外部依赖,适合嵌入式或极简场景。
✅ 总结
避免 int(f * scale) 的裸转换;始终使用 roundToInt(f * scale) 封装逻辑。它以最小开销解决浮点精度导致的舍入偏差,兼顾正负数一致性,是 Go 中处理货币、计量、序列化等场景下「浮点→缩放整数」转换的标准实践。










