Python round() 实际采用“四舍六入五成双”而非四舍五入,如 round(2.5) 得 2、round(3.5) 得 4;浮点数二进制精度限制导致 round(2.675,2) 结果为 2.67;需用 decimal 模块实现真正四舍五入。

Python round() 真的是四舍五入吗?
不是。Python 的 round() 默认用的是「四舍六入五成双」(也叫银行家舍入),不是小学教的四舍五入。比如 round(2.5) 得 2,round(3.5) 得 4,因为要向偶数靠拢。
这规则能减少统计偏差,但如果你写财务、教学或和 Excel 对结果,就容易踩坑——Excel 默认四舍五入,而 Python 不是。
- 只对浮点数和整数生效;传字符串会报
TypeError - 当小数位数为 0(即取整)时,行为最明显,也是最容易误判的场景
-
round(1.234, 2)→1.23,round(1.235, 2)→1.24?错,实际是1.23(因为 1.235 在二进制中无法精确表示,真实值略小于 1.235,所以向下舍)
怎么实现真正的四舍五入?
得绕开 round(),自己构造逻辑。最稳妥的是用 decimal 模块,它按十进制算,可控、无二进制误差。
如果只是简单场景(比如展示用),也可以用 math.floor(x + 0.5) 向上偏移再截断,但仅适用于正数;负数得用 math.copysign(math.floor(abs(x) + 0.5), x)。
立即学习“Python免费学习笔记(深入)”;
-
decimal.Decimal('2.675').quantize(decimal.Decimal('0.01'), rounding=decimal.ROUND_HALF_UP)→Decimal('2.68') - 别用
float初始化Decimal:写Decimal('2.675'),别写Decimal(2.675),否则又带入浮点误差 - 性能上
decimal比原生float慢一个数量级,高频计算慎用
为什么 round(2.675, 2) 结果是 2.67 而不是 2.68?
因为 2.675 在 IEEE 754 浮点中无法精确存储,实际存的是比它略小的数(比如约 2.6749999999999998),round() 拿这个近似值去算,自然向下舍了。
- 用
repr(2.675)就能看到真相:'2.67499999999999982236431605997495353221893310546875' - 所有用小数点写的浮点字面量,只要不能被 2 的幂整除,都可能有这种隐式偏差
- 这不是 bug,是浮点数表示原理决定的,任何语言都一样
该用哪个函数?看场景选
没银弹。选法取决于你真正在意什么:精度、速度、可读性,还是和外部系统对齐。
- 做金额计算、审计、测试断言 → 必用
decimal+ROUND_HALF_UP - 做科学计算、大量数组运算 → 接受
round()的银行家规则,或用numpy.round()(行为一致,但支持向量化) - 只是格式化输出给用户看 → 用
f'{x:.2f}',它底层调用的是round_half_up风格(C 标准库行为),和 Excel 表现更接近 - 注意:
str.format()和f-string的舍入在 Python 3.12+ 才完全统一,旧版本可能有细微差异
真正麻烦的从来不是“怎么写”,而是“你有没有意识到,同一个数字在内存里根本不是你以为的那个数字”。










