7

如果我在 java 程序中对 Random 使用相同的种子值并在两台不同的机器上运行它,我会得到相同的数字集吗?

例如

    long seed = 123L;//may be taken from some database or something
    java.util.Random ran = new java.util.Random(seed);
    int ret = 0;
    for (int i= 0; i< 10; i++){
        ret = ran.nextInt(1000);
        System.out.println("ret="+ret);
    }

我总是得到

ret=782
ret=450
ret=176
ret=789
ret=795
ret=657
ret=834
ret=837
ret=585
ret=453

如果我在我的计算机上多次运行,我会得到相同的一组数字.. 但是假设有人设法获得我使用的秘密种子值(通过猜测或从存储它的秘密位置)并运行此代码他的机器,他会得到相同的数字吗?

4

4 回答 4

8

是的,指定随机数生成方式的合约在两种情况下都是相同的,因此如果给定相同的种子,它们将产生相同的数字序列。的实现Random必须使用规定的算法以确保是这种情况。一种更精确的放置方式(来自相关文档)是:

如果使用相同的种子创建 Random 的两个实例,并且为每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。为了保证这一特性,为类 Random 指定了特定的算法。为了 Java 代码的绝对可移植性,Java 实现必须使用此处为类 Random 显示的所有算法。但是,允许类 Random 的子类使用其他算法,只要它们遵守所有方法的通用合同。

于 2013-06-23T12:19:31.827 回答
3

JRE 应该生成相同的随机数序列,因为它们使用相同的种子,并且使用了算法。Random上的 Java 文档说:

如果使用相同的种子创建 Random 的两个实例,并且为每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。

所有 JRE 实现也使用这些算法:

为了保证这一特性,为类 Random 指定了特定的算法。为了 Java 代码的绝对可移植性,Java 实现必须使用此处为类 Random 显示的所有算法。但是,允许类 Random 的子类使用其他算法,只要它们遵守所有方法的通用合同。

于 2013-06-23T12:21:53.077 回答
2

是的,这就是重点。

例如:在 Minecraft 中,您可以获得关卡种子来初始化随机生成器,每个拥有此种子的男孩都会获得相同的地图。

如果您阅读JavaDoc,您会看到next(int bits)(并且nextInt()只是next(32))将种子更新为(seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)并返回(int)(seed >>> (48 - bits))。对于相同的种子,在任何计算机上总是相同的。

于 2013-06-23T12:21:46.060 回答
1

答案是肯定的,因为 Random.nextInt() 的方式是被执行的。它只是使用种子并进行一些计算来生成数字。该代码不使用任何机器特定的参数来生成。下面是 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;
 }

在此处阅读有关 Random nextInt 方法的更多信息:

http://docs.oracle.com/javase/6/docs/api/java/util/Random.html#nextInt(int)

于 2013-06-23T12:23:01.830 回答