math.abs()对最小值溢出返回负数,math.max()遇nan返回nan而非抛异常;math.round()类型不一致且用银行家舍入;math.pow()性能差、边界敏感,应优先用乘法或math.sqrt()。

Math.abs() 和 Math.max() 处理负数时容易返回意外结果
Java 的 Math.abs() 对 Integer.MIN_VALUE 和 Long.MIN_VALUE 会溢出,直接返回原值(仍是负数);Math.max(a, b) 在任一参数为 NaN 时恒返回 NaN,不是抛异常——这点常被误认为“计算出错”。
- 用
Math.abs()前先判断是否为最小值:if (x == Integer.MIN_VALUE) { /* 特殊处理 */ } - 涉及用户输入或外部数据时,优先用
Math.toIntExact(Math.abs((long)x))防溢出(需 JDK 8+) -
Math.max()不适合做空值保护,若 a 或 b 可能为NaN,应先用Double.isNaN()过滤
Math.round() 的舍入规则和类型陷阱
Math.round(float) 返回 int,Math.round(double) 返回 long——类型不一致导致隐式转换错误很常见。而且它用的是“四舍五入到最近偶数”(银行家舍入)的底层逻辑,不是简单四舍五入。
- 想对 double 保留两位小数并转成 double?别写
Math.round(x * 100) / 100.0,它在x = 0.145时可能得0.14(因浮点误差 + 舍入规则) - 更稳的方式是用
BigDecimal:new BigDecimal(x).setScale(2, RoundingMode.HALF_UP).doubleValue() - 如果坚持用
Math.round(),确保除数类型匹配返回值,比如Math.round(3.7f)→int,而Math.round(3.7)→long
Math.pow() 性能差且对边界值敏感
Math.pow() 是通用幂函数,底层调用 native 实现,比直接乘法慢 10 倍以上;同时对 0^0、负底数的分数指数等组合返回 NaN 或 Infinity,但不会报错,容易埋下静默 bug。
- 整数小次方(如平方、立方)直接写
x * x或x * x * x,别用Math.pow(x, 2) - 需要开方?优先用
Math.sqrt(x),它比Math.pow(x, 0.5)快且语义清晰 - 底数可能为负、指数非整数时,必须提前校验:
if (base
Math.random() 不能用于安全或高精度场景
Math.random() 基于 java.util.Random,周期短、可预测、线程不安全;生成 [0.0, 1.0) 的 double,但实际分辨率只有约 2⁻⁵³,且无法指定种子。
立即学习“Java免费学习笔记(深入)”;
- 要可重现的随机数(如测试),改用
new Random(123L)实例,再调nextDouble() - 密码学用途?必须用
SecureRandom,Math.random()完全不适用 - 想生成区间
[a, b)的整数?别写(int)(Math.random() * (b - a)) + a,浮点截断可能导致分布偏差;改用ThreadLocalRandom.current().nextInt(a, b)
Math 类看着简单,但每个方法背后都有类型、精度、边界、性能四层坑。最常被忽略的是:它不处理 NaN/Infinity 的传播逻辑,也不做参数校验——所有“看起来该报错的地方”,它都选择沉默返回。









