math.round() 实际是先加0.5再向下取整,导致负数结果反直觉;math.floor() 是向下取整而非截断小数,返回≤原值的最大整数且类型为double。

Math.round() 不是简单四舍五入,Math.floor() 也不是“去掉小数”——用错会导致负数结果反直觉,尤其在金额、分页、索引计算中出错。
Math.round() 的真实行为:加 0.5 后 floor
它底层等价于 Math.floor(x + 0.5),所以对负数的处理和直觉相反:
-
Math.round(2.5)→ 3(2.5 + 0.5 = 3.0 →floor(3.0)= 3) -
Math.round(-2.5)→ -2(-2.5 + 0.5 = -2.0 →floor(-2.0)= -2) -
Math.round(-2.6)→ -3(-2.6 + 0.5 = -2.1 →floor(-2.1)= -3)
注意返回类型:round(double) 返回 long,round(float) 返回 int。混用时容易触发隐式截断,比如把 long 结果直接赋给 int 变量而没检查溢出。
Math.floor() 是向下取整,不是截断小数
它返回「小于或等于参数的最大整数」,结果始终 ≤ 原值,且返回类型固定为 double:
-
Math.floor(3.9)→ 3.0 -
Math.floor(-3.1)→ -4.0(不是 -3!因为 -4 -
Math.floor(0.0)→ 0.0,Math.floor(-0.0)→ -0.0(IEEE 754 区分正负零)
常见误用:想取整数部分就写 (int) Math.floor(x)。这在 x ≥ 0 时没问题,但 x 为负大数(如 -1e10)时,int 会溢出,应改用 Math.floorDiv() 或显式转 long。
什么时候该用 round,什么时候该用 floor?
看目标语义,而不是“看起来像四舍五入”:
- 需要「最接近的整数」且接受负数特殊规则 → 用
Math.round()(如统计平均值取整) - 需要「不超过原值的最大整数」→ 用
Math.floor()(如分页计算总页数:(int) Math.ceil(total / (double) size)实际依赖floor的逆运算) - 做金额四舍五入到分?别用
Math.round(x * 100) / 100.0——浮点误差会让1.235变成1.234999999,round后得 123 而非 124。应改用BigDecimal或整数运算
floor 和 round 在边界值上的典型陷阱
这两个方法在 Double.MIN_VALUE、Double.MAX_VALUE、NaN、无穷值上行为不同:
-
Math.floor(Double.NaN)→NaN;Math.round(Double.NaN)→0(不是异常!) -
Math.floor(Double.POSITIVE_INFINITY)→Infinity;Math.round(Double.POSITIVE_INFINITY)→Long.MAX_VALUE -
Math.floor(-0.0)→-0.0;Math.round(-0.0)→0(符号丢失)
这些细节在金融、物理模拟或高精度计时里可能暴露,但多数业务代码连 Double.isFinite() 都没校验,直接传进去就埋了雷。










