Python中round()仅四舍五入,无法截断小数;需用math.floor(x*100)/100实现向下截断(负数也正确),或decimal.Decimal.quantize(..., rounding=ROUND_DOWN)确保金融级精度。

Python 中 round() 不能截断小数,它默认四舍五入
很多人误以为 round(3.145, 2) 能“控制两位小数”,但其实它会四舍五入成 3.15;更关键的是,当目标是「截断」(即直接砍掉第三位及之后,不进位)时,round() 完全不适用。比如 round(1.239, 2) → 1.24,而你想要的是 1.23。
用 math.floor() 配合缩放实现向下截断
核心思路:把数字放大 100 倍 → 向下取整 → 再除以 100。注意必须用 math.floor()(不是 int()),否则负数会出错(int(-1.239 * 100) 是 -123,但 math.floor(-123.9) 才是 -124,这才是真正向下截断)。
- 正数示例:
math.floor(1.239 * 100) / 100→123.0 / 100→1.23 - 负数示例:
math.floor(-1.239 * 100) / 100→math.floor(-123.9)→-124.0 / 100→-1.24(符合“向负无穷截断”语义) - 如果业务要求「所有数都朝零截断」(即 -1.239 → -1.23),那就得用
int(x * 100) / 100,但要清楚这在负数上不是数学意义的截断
转字符串再切片虽简单,但要注意浮点表示误差
直接 str(x) 然后找小数点位置切片,看似直观,但 Python 浮点数二进制存储会导致意外结果。例如 str(1.005) 可能返回 '1.0049999999999999',切出的就不是 '1.00' 而是 '1.00' 或 '1.01',完全不可控。
- 仅适用于已知是“安全浮点数”的场景(如从字符串解析、或经
decimal处理过) - 若原始数据来自用户输入或数据库,优先走数值计算路径(上一条的
math.floor方案) - 字符串方案示例(慎用):
s = f"{x:.10f}"; i = s.find('.'); s[:i+3] if i != -1 else s—— 但 .10f 不保底,仍可能暴露精度问题
用 decimal.Decimal 是最稳妥的金融级方案
当精确性不可妥协(比如金额计算),必须用 decimal。它支持明确的舍入策略,包括 ROUND_DOWN(即截断)。
立即学习“Python免费学习笔记(深入)”;
- 先转
Decimal:from decimal import Decimal, ROUND_DOWN; d = Decimal(str(x))(注意:必须用str(x)构造,避免 float 二进制误差) - 再量化:
d.quantize(Decimal('0.01'), rounding=ROUND_DOWN) - 输出为 float 或 str:
float(d.quantize(...))或str(d.quantize(...)) - 缺点是性能略低、代码稍长,但这是唯一能 100% 控制行为的方式
实际中,多数人忽略负数行为差异和浮点表示陷阱,直接用 math.floor(x * 100) / 100 就够用;但只要涉及钱,decimal 不是可选项,是必选项。










