Reputation: 16703
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?
Upvotes: 4
Views: 876
Reputation: 328619
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);
}
Upvotes: 7
Reputation: 2784
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()); }
Upvotes: 2
Reputation: 3436
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...
Upvotes: 0