随机数的绝对值不正确¶
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 整数类型和值。