这个破坏的Java Random.nextInt(长)行为怎么了?

Nic*_*olt 8 java random

我发现这种方法似乎在你给它2的幂时失败了很难.鉴于两个不同种子的随机对象,它们似乎是当被要求返回0(包括)和之间的整数时返回的第一个整数两个(独占)的力量总是一样的; 种子没关系.例如:

public static void main(String[] args) {
    Random mRandom;
    for (int i = 0; i < 10; i++) {
        mRandom = new Random(i);            
        System.out.println(mRandom.nextInt((int) Math.pow(2, 4)));
    }
}

Console:
11
11
11
11
11
11
11
11
11
11
Run Code Online (Sandbox Code Playgroud)

我任意选择2 ^ 4,但它似乎适用于任何2的幂.这是怎么回事?此外,我该如何避免这种情况?

Mas*_*dul 5

出现此问题的原因有两个.

  1. Random上课同样的种子.
  2. nextInt(int n),如果n是2的幂

1.随机类的相同种子.

因为,您已Random使用新seed值启动了新实例,这会对nextInt值生成产生影响.根据爪哇的Java文档(长种子).

使用单个长种子创建新的随机数生成器.种子是伪随机数生成器的内部状态的初始值,它由方法next(int)维护.

The invocation new Random(seed) is equivalent to:

 Random rnd = new Random();
 rnd.setSeed(seed);
Run Code Online (Sandbox Code Playgroud)

如果你尝试生成随机值new seed,即使是新的Random类实例,也不会产生真正的随机值.

for (int i = 0; i < 10; i++) {
    mRandom = new Random();   // Without seed         
    System.out.println(mRandom.nextInt((int) Math.pow(2, 4)));
}
Run Code Online (Sandbox Code Playgroud)

输出: 2 1 12 4 3 9 9 8 2 9

2.在nextInt(int n),如果n是2的幂

除此之外,Random#nextInt具有2的幂的效果.如果n是2的幂,它将返回(int)((n * (long)next(31)) >> 31),对于相同的n,它将总是相同.根据nextInt算法,

public int nextInt(int n) {
   if (n <= 0)
     throw new IllegalArgumentException("n must be positive");

   if ((n & -n) == n)  // i.e., n is a power of 2
     return (int)((n * (long)next(31)) >> 31);

   int bits, val;
   do {
       bits = next(31);
       val = bits % n;
   } while (bits - val + (n-1) < 0);
   return val;
 }
Run Code Online (Sandbox Code Playgroud)

  • 我认为OP问题在于十个不同的种子产生相同的随机数. (2认同)
  • 它并不总是一样的.如果用`pow(2,8)`运行它100个循环,你会开始看到它颤动. (2认同)