2012-03-16 18 views
4

を播種する場合は、次のコードは、同一の種を持つ2つのランダムオブジェクトを作成する必要があります出力に示すようにSystem.currentTimeMillis()は、2つのオブジェクトを作成する前と後に変化しなかったので、奇妙な行動のJavaランダム

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()); 

を種子が同一である必要があります:ドキュメントから

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

、引数なしコンストラクタは、単純です:

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

それで何ができますか?同じ種子を持つべきときに2つの発電機が異なる出力を返す理由を誰でも説明できますか?

+0

にヘッダに探し ' + は'メソッドのソースを表示します。 –

+0

"System.currentTimeMillis()は2つのオブジェクトの作成前後で変更されていないため、シードは同じである必要があります" - それが本当であるという保証はありません。 – Jesper

答えて

7

java.util.Randomを使用している場合は、これはデフォルトのno-argsコンストラクタです。 JDKのあなたは(このコードは、少なくとも日JDK 6 & 7のために使われているようです)を使用している:

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

そして、ちょうどここに、それを確認するためには、種が同一であるかどうかを確認するためのコードです:

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); 
} 
+0

私のクイック・グーグル・サーチは、[これ](http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html)に掲載されました。 – Flash

+0

@AndrewこれはJava 1.4.2から – artbristol

+0

@Andrewを私のIDEに入れたものです。 – assylias

0

2つのジェネレータは同じシードを持つ必要がある場合、異なる出力を返しますか?

?あなたのジェネレータのうちの1つだけがmillis seedを取得しているように見えます。

2

私はデフォルトのコンストラクタがあなたの言うことをしないと思います(つまり、public Random { this(System.currentTimeMillis()); } Javaのドキュメントでは、呼び出すたびに異なる可能性のある値を持つクラスを初期化していることがわかりますhereRandomする(Mac OS X)の私の実装を行うことができますほとんどのIDEで

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