2016-07-14 16 views
-2

Ich schrieb eine Demo zu testen java.util.Random und ich möchte eine wiederholte Liste der gleichen 5 Zahlen zu erzeugen, aber ich bekomme den gleichen Wert, wenn Sie verschiedene Samen. In meinem Programm reichen die Samen von 0 bis 4. Soweit ich weiß, erzeugen verschiedene Samen unterschiedliche Werte und derselbe Samen erhält den gleichen Wert. Also ich denke, das Ergebnis wird eine sich wiederholende Liste der gleichen 5 Zahlen sein. Aber die tatsächlichen Werte sind alle gleich. Was ist falsch an meinem Code? Kann mir das jemand sagen?Java Random.nextInt (int) den gleichen Wert zurückgeben, wenn verschiedene Samen gesetzt

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

Das Ergebnis ist:

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 
... 
... 
... 
+0

Die wahrscheinlichere Antwort ist, dass es einen Fehler in Ihrem Code gibt. Sie sollten die verschiedenen Teile isolieren und testen, ob Sie tun, was Sie denken, dass Sie tun. – Silverclaw

+4

nicht sicher, was Sie erreichen möchten, aber es ist nicht, wie Sie Random verwenden. Sie legen einmal den Startwert fest und nehmen dann Zahlen daraus. – mlecz

+0

Versuchen Sie einfach 'int randomNum = rand.nextInt (max) + min;' Es ist auch erwähnenswert, dass jedes Mal, wenn Sie das Seed ändern, es zurückgesetzt wird, so dass Sie in diesem Fall eine Wiederholungsliste der gleichen 5 Zahlen erhalten. – Andrew

Antwort

3

Soweit ich weiß, verschiedene Samen verschiedene Werte

produzieren Dies ist falsch, verschiedene Samen können unterschiedliche Werte erzeugen, Sie können auch die gleichen Werte erzeugen.

Es gibt 2^64 mögliche Samen und rand.nextInt(256) kann nur 256 verschiedene Werte zurückgeben so viele der Samen müssen den gleichen Wert zurückgeben.

Auch die setSeed javadoc Staaten

Die Implementierung von setSeed nach Klasse Zufalls nur 48 Bits des gegebenen Samen

Also, wenn Ihr Samen alle nur zu verwenden, geschieht die ignoriert Bits unterscheidet sich darin, der Werte werden gleich sein.

+0

"verschiedene Samen produzieren unterschiedliche Werte" ist falsch. Produziert derselbe Seed auf verschiedenen Plattformen und Geräten denselben Wert? – dragonfly

+0

@dragonfly Ja, es sei denn, es gibt einen Bug in der 'Random' Implementierung der Plattform. Das Javadoc benötigt den gleichen Seed, um in allen Java-Implementierungen die gleichen Werte zu erzeugen. Beachten Sie, dass sich einige der Methoden wie 'nextFloat' und' nextDouble' im Laufe der Zeit geändert haben und sich in der Zukunft möglicherweise wieder ändern, sodass Sie möglicherweise nicht dieselben Werte erhalten, wenn Sie andere Java-Versionen verwenden. – Alex

+1

@dragonfly Es sieht auch so aus, als würde 'Random'' 'strictfp' nicht verwenden, so dass die Methoden, die Gleitkommazahlen verwenden, leicht unterschiedliche Ergebnisse über die Plattformen hinweg erzeugen können. – Alex

0

Ich habe diese Implementierung auf grepcode gefunden, es gibt eine if-Anweisung, um festzustellen, ob n eine Potenz von 2 ist. Wenn n (d. H. Die Grenze) eine Potenz von 2 (int)((n * (long)next(31)) >> 31); ist.

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

Ich weiß nicht, ob diese Umsetzung in Ihrem JDK verwendet wird, aber dies legt nahe, dass Potenz von 2 Grenzen unterschiedlich behandelt werden.

Der Algorithmus behandelt den Fall, in dem n eine Zweierpotenz ist, speziell: Er gibt die korrekte Anzahl der höherwertigen Bits aus dem zugrunde liegenden Pseudozufallszahlengenerator zurück. In Abwesenheit einer speziellen Behandlung würde die korrekte Anzahl von Bits niedriger Ordnung zurückgegeben werden. Lineare kongruente Pseudozufallszahlengeneratoren, wie der von dieser Klasse implementierte, haben bekanntermaßen kurze Perioden in der Folge von Werten ihrer niederwertigen Bits. Somit erhöht dieser spezielle Fall die Länge der Folge von Werten, die von aufeinanderfolgenden Aufrufen dieser Methode zurückgegeben werden, stark, wenn n eine kleine Potenz von zwei ist.