随机数的绝对值不正确¶
ID: java/abs-of-random
Kind: problem
Security severity:
Severity: warning
Precision: medium
Tags:
- reliability
- maintainability
Query suites:
- java-security-and-quality.qls
对 Random.nextInt()(或 Random.nextLong())调用的结果使用 Math.abs 不能保证返回非负数。 Random.nextInt() 可以返回 Integer.MIN_VALUE,当将其传递给 Math.abs 时,结果为相同的值 Integer.MIN_VALUE。(由于 Java 中整数采用二进制补码表示,因此 Integer.MIN_VALUE 的正等价值无法用相同数量的位表示。) Random.nextLong() 的情况类似。
建议¶
如果需要非负随机整数,请改用 Random.nextInt(int),并使用 Integer.MAX_VALUE 作为其参数。可能返回的值不包括 Integer.MAX_VALUE 本身,但此解决方案可能足以满足大多数目的。
另一种解决方案是在将结果传递给 Math.abs 之前,如果 Random.nextInt() 为负数,则将其值加 1。此解决方案的优点是 0 与其他数字具有相同的概率。
示例¶
在以下示例中,如果 nextInt 返回 Integer.MIN_VALUE,则 mayBeNegativeInt 为负数。此示例展示了如何使用上面描述的两个解决方案,这意味着 positiveInt 始终被分配一个正数。
public static void main(String args[]) {
Random r = new Random();
// BAD: 'mayBeNegativeInt' is negative if
// 'nextInt()' returns 'Integer.MIN_VALUE'.
int mayBeNegativeInt = Math.abs(r.nextInt());
// GOOD: 'nonNegativeInt' is always a value between 0 (inclusive)
// and Integer.MAX_VALUE (exclusive).
int nonNegativeInt = r.nextInt(Integer.MAX_VALUE);
// GOOD: When 'nextInt' returns a negative number increment the returned value.
int nextInt = r.nextInt();
if(nextInt < 0)
nextInt++;
int nonNegativeInt = Math.abs(nextInt);
}
参考¶
Java API 规范:Math.abs(int)、Math.abs(long)、Random。
Java 语言规范:4.2.1 整数类型和值。