Weird behaviour when seeding Java Random

旧巷老猫 提交于 2020-01-02 07:01:18

问题


The following code should create two Random objects with identical seeds:

System.out.println("System time before: " + System.currentTimeMillis());
Random r1 = new Random();
Random r2 = new Random(System.currentTimeMillis());
System.out.println("System time after: " + System.currentTimeMillis());

System.out.println("r1: " + r1.nextInt());
System.out.println("r2: " + r2.nextInt());

The seeds should be identical since System.currentTimeMillis() did not change before and after creating the two objects as shown in the output:

System time before: 1331889186449
System time after: 1331889186449
r1: -1836225474
r2: 2070673752

From the docs, the constructor without any arguments is simply:

public Random() { this(System.currentTimeMillis()); }

So what gives? Can anyone explain why the two generators return different outputs when they should have the same seed?


回答1:


If you are using java.util.Random, this is the default no-args constructor I see - now it might depend on the version of JDK you are using (this code seems to be used for sun JDK 6 & 7 at least):

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

And just to confirm it, here is a code to check if the seeds are identical:

public static void main(String args[]) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    System.out.println("System time before: " + System.currentTimeMillis());
    Random r1 = new Random();
    Random r2 = new Random(System.currentTimeMillis());
    System.out.println("System time after: " + System.currentTimeMillis());

    Field seed = Random.class.getDeclaredField("seed");
    seed.setAccessible(true);
    AtomicLong seed1 = (AtomicLong) seed.get(r1);
    AtomicLong seed2 = (AtomicLong) seed.get(r2);

    System.out.println("seed1 = " + seed1);
    System.out.println("seed2 = " + seed2);
}



回答2:


I don't think that the default constructor does what you say it does (i.e., public Random { this(System.currentTimeMillis()); } The java documentation just says that it is initialising the class with a value that is likely be different on each invocation here. Looking in a header in my implementation of Random (Mac OS X)

public Random() { this(++seedUniquifier + System.nanoTime()); }



回答3:


the two generators return different outputs when they should have the same seed?

they do? it looks to me that only one of your generators is getting the millis seed...



来源:https://stackoverflow.com/questions/9734606/weird-behaviour-when-seeding-java-random

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!