Java Random.nextInt(int) return 设置不同种子时相同的值

Java Random.nextInt(int) return the same value when set different seeds

我写了一个演示来测试 java.util.Random 我想生成一个包含相同 5 个数字的重复列表,但是当设置不同 seeds.In 我的程序时我得到相同的值,种子范围从0到4。据我所知,不同的种子产生不同的值,相同的种子获得相同的值。所以我认为结果将是相同 5 个数字的重复列表。但是输出的实际值都是一样的。我的代码有什么问题?谁能告诉我吗?

import java.util.Random;

public class Main {
    public Main() {
    }

    public static void main(String[] args) {
        for (int i = 0 ; i <= 255; i++)
        {
            String hex = Integer.toHexString(randInt(0, 255, i % 5));
            System.out.println(hex);
        }
    }
    private static Random rand = new Random();
    public static int randInt(int min, int max, long seed) {
        rand.setSeed(seed);
        System.out.println("seed:" + seed);
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }
}

结果是:

seed:0
bb
seed:1
bb
seed:2
bb
seed:3
bb
seed:4
bb
seed:0
bb
seed:1
bb
seed:2
bb
seed:3
bb
seed:4
bb
seed:0
bb
seed:1
bb
seed:2
bb
seed:3
bb
seed:4
bb
seed:0
bb
seed:1
...
...
...

As far as I know, different seeds produce different values

这是不正确的,不同的种子可能产生不同的值,它们也可以产生相同的值。

有 2^64 个可能的种子,rand.nextInt(256) 只能 return 256 个不同的值,因此许多种子必须 return 相同的值。

setSeed javadoc 也指出

The implementation of setSeed by class Random happens to use only 48 bits of the given seed

因此,如果您的种子仅在忽略的位上有所不同,则所有值都将相同。

我在 grepcode 上找到了这个实现,有一个 if 语句来检测 n 是否是 2 的幂。如果 n(即边界)是 2 的幂,则使用 (int)((n * (long)next(31)) >> 31); .

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;
}

我不知道您的 JDK 中是否使用了此实现,但这表明 2 次方边界的处理方式不同。

The algorithm treats the case where n is a power of two specially: it returns the correct number of high-order bits from the underlying pseudo-random number generator. In the absence of special treatment, the correct number of low-order bits would be returned. Linear congruential pseudo-random number generators such as the one implemented by this class are known to have short periods in the sequence of values of their low-order bits. Thus, this special case greatly increases the length of the sequence of values returned by successive calls to this method if n is a small power of two.