math.random()生成[0,1)的double,获取1~6随机整数应写为(int)(math.random()*6)+1;math.abs(integer.min_value)仍返回负值,可用math.absexact()避免;2的n次方优先用1l

Math.random() 生成的是 [0, 1) 区间的 double,不是整数
很多人想用 Math.random() 直接得到 1~6 的随机整数,结果写成 Math.random() * 6 就直接用了——这得到的是 double,而且范围是 [0, 6),不是 [1, 6]。
正确做法是先乘区间长度、加下界,再强制转 int(注意是截断,不是四舍五入):
int dice = (int)(Math.random() * 6) + 1; // [1, 6]
- 别用
Math.round(),它会让 0.5 和 5.5 都往中间偏,两端概率变低 - 需要线程安全或更高质量随机数时,改用
ThreadLocalRandom.current().nextInt(1, 7) -
Math.random()内部复用同一个java.util.Random实例,高并发下有竞争,性能略差
Math.abs() 对 Integer.MIN_VALUE 返回负值?没错,这是溢出
Math.abs(int) 在输入为 Integer.MIN_VALUE(即 -2147483648)时,返回的仍是 -2147483648。这不是 bug,是整数补码表示下的必然结果:它的相反数超出了 int 正数范围。
类似问题也出现在 Math.abs(long) 遇到 Long.MIN_VALUE 时。
立即学习“Java免费学习笔记(深入)”;
- 如果业务逻辑依赖“绝对值一定非负”,必须提前检查:
if (x == Integer.MIN_VALUE) throw new IllegalArgumentException(); - 用
Math.absExact()(Java 8+)可自动抛出ArithmeticException,比手动判断更明确 -
Math.abs(float)和Math.abs(double)没这个问题,因为浮点数没有对称的最小值
Math.pow() 算 2 的 n 次方?别用它,位运算更快更准
Math.pow(2, n) 看起来简洁,但它是基于 double 的通用幂函数,有精度损失和性能开销。比如 Math.pow(2, 30) 可能返回 1073741824.0(看着对),但 Math.pow(2, 60) 就开始丢精度,变成近似值。
整数幂且底数为 2 时,一律用左移:1L 。
1 是 <code>int,n ≥ 31 会溢出;要支持更大指数,必须写1L-
Math.pow()对特殊值敏感:如Math.pow(0, 0)返回1.0,Math.pow(-1, 0.5)返回NaN - 真要算非 2 的整数幂(如 3⁵),用循环乘比
Math.pow()更可控,尤其当结果需为long且不能容忍浮点误差时
Math.floorDiv() 和 / 运算符对负数结果不同,选错会出逻辑错误
Java 8 引入了 Math.floorDiv(),它和普通整数除法 / 的关键区别在负数取整方向:/ 向零截断,floorDiv 向负无穷取整。
例如:Math.floorDiv(-7, 3) 是 -3,而 -7 / 3 是 -2。
- 分页计算页码时常用
(index - 1) / size,但如果index可能为 0 或负,就该换Math.floorDiv(index - 1, size)保证一致性 - 配合
Math.floorMod()使用才能保持恒等式:floorDiv(x, y) * y + floorMod(x, y) == x;而%和/不满足这个 - 注意
Math.floorDiv(int, int)和Math.floorDiv(long, long)都有,但没提供float/double版本
实际用的时候,最常踩坑的是 Math.abs() 的溢出和 Math.pow() 的精度漂移——这两个点不盯住,上线后可能在边界数据上静默出错,还不好复现。









