2010-12-03 4 views
4

Ich hatte viele Probleme mit der Randomisierung von Listen. Ich spreche von einer Liste von 200 Elementen, wo ich die Liste mischen möchte. Verstehen Sie mich nicht falsch, ich lese viel von Beispielen, und auf den ersten Blick gibt es ziemlich schöne Dinge, wie folgt aus:C# Zufällige Codes - Ist das meiste einfach falsch?

Randomize a List<T>

Aber in meiner Erfahrung, zumindest auf einer schnellen Maschine, das ist grundsätzlich wertlos. Das Mischen funktioniert so schnell, dass zwischen zwei Aufrufen von Random.NEXT() KEINE MS-Verzögerung auftritt, was zu nicht annähernd zufälligem Verhalten führt.

ich über Super sichere Sachen rede nicht nur ein Grundspiel zufällig. Ich weiß, dass ich eine Verzögerung von 1 MS hinzufügen kann, aber das bedeutet "Verschwendung" von 200 MS, nur um eine Liste zufällig zu machen.

Nun fand ich diesen Ansatz: http://www.codinghorror.com/blog/2007/12/shuffling.html

Es sieht nett aus, zu sortieren GUIDs zu verwenden. ABER sind sie nicht auf die gleiche Weise erstellt? Läßt es Schritt eine Kerbe, läßt vermuten, ich 1000 Nummern erstellt werden soll, zwischen 0 - 5 Dieser Code im Grunde nutzlos ist:

 var resultA = new List<int>(); 
     for (int i = 0; i < 1000; i++) 
     { 
      resultA.Add(new Random().Next(5)); 
     } 


     var resultB = new List<int>(); 
     for (int i = 0; i < 1000; i++) 
     { 
      resultB.Add(new Random().Next(5)); 
      Thread.Sleep(1); 
     } 

A überhaupt nicht funktionieren, zumindest nicht meine Umgebung in Windows Phone im, 7. B ist in Ordnung, aber es dauert eine Sekunde, die auch dumm ist. Irgendwelche Kommentare oder Gedanken, es kann nicht so schwer sein, eine zufällige Liste von ganzen Zahlen zu erstellen :-)

+0

Oh, ich mich wirklich hassen jetzt :-) Ok, das erklärt es .. Nun gab es einige Fragen, bei denen es sinnvoll, eine neue Zufalls (jede Frage zu verwenden gemacht wurde erstellt, und es sollte das Element platzieren in 1-4, so die Frage kümmerte sich um das Ganze), aber sie waren zu schnell erstellt .. Ok, danke trotzdem, habe meinen dummen Fehler !! –

+0

Verwenden Sie die Shuffle-Erweiterung für die Frage, auf die Sie verwiesen haben - oder sehen Sie, ob Sie Jon Skeets Implementierung finden können, es ist eine andere Frage. Aufeinanderfolgende Aufrufe von Next() auf demselben RNG sollten normalerweise andere Werte zurückgeben (obwohl es "zufällig" ist, sodass Sie in regelmäßigen Abständen doppelte Daten erhalten). – tvanfosson

+0

Ja, und mit den Fragen verschiebe ich einfach den Zufallsgenerator zum Elternobjekt (das Spiel), also gibt es kein Problem mehr. Aber trotzdem, es ist lustig, wie lange du nach diesem blöden Fehler suchen kannst, und ich war mir sicher, dass "Zufallszahlen" nicht so schwer sein können. Sollte früher gefragt haben :-) –

Antwort

22

Nicht weiter initialisieren eine neue Instanz von Random; mache nur einen und referenziere ihn ständig.

var random = new Random(); 
var resultA = new List<int>(); 
for (int i = 0; i < 1000; i++) 
{ 
    resultA.Add(random.Next(5)); 
} 

Sie sind richtig, dass immer wieder neue Instanzen von Random innerhalb der gleichen „Zeitstempel“ im gleichen Samen führt zu schaffen; Wenn Sie jedoch .Next für eine Instanz von Random aufrufen, wird der Seed "weitergeschaltet", sodass die nächste Nummer, die Sie abrufen, (wahrscheinlich) anders ist.

Dies spiegelt sich auch in the documentation on Random bedeckt:

... denn die Uhr hat eine begrenzte Auflösung, die parameterlosen Konstruktor mit verschiedenen Zufalls Objekte in dichter Folge Zufallszahlengeneratoren erzeugt zu erzeugen, die identische Sequenzen von Zufallszahlen erzeugen .

...

Dieses Problem kann durch die Schaffung eines einzigen Random-Objekt anstatt mehrere diejenigen vermieden werden.

+0

Die so ziemlich die Frage hier von Mark und Bronumski bedeckt, so dass ich ihn nur als zusätzliche Informationen hinzufügen. Stellen Sie sich Pseudozufallszahlengeneratoren als eine mathematische Sequenz vor. Wenn Sie es instanziieren, wird es gesetzt, nachfolgende Aufrufe werden pseudo-Zufallszahlen aus der Sequenz erzeugen. Sie werden als "pseudo random" bezeichnet, weil sie nur zufällig erscheinen, wenn tatsächlich nur Zahlen aus der Sequenz zurückgegeben werden. Pseudozufallszahlengeneratoren werden manchmal gegeneinander bewertet wegen ihrer Fähigkeit, zufällig zu erscheinen. –

6

Sie müssen dieselbe Instanz von Random behalten.

var random = new Random(); 

    var resultA = new List<int>(); 
    for (int i = 0; i < 1000; i++) 
    { 
     resultA.Add(random.Next(5)); 
    } 


    var resultB = new List<int>(); 
    for (int i = 0; i < 1000; i++) 
    { 
     resultB.Add(random.Next(5)); 
     Thread.Sleep(1); 
    } 

Dies liegt daran, wenn Zufalls initialisiert es die Systemuhr verwendet einen Zeitpunkt zu erhalten. Wenn Sie als nächstes anrufen, kann die Zeitdifferenz verwendet werden, um die nächste Nummer zu erhalten. Wenn Sie ein Random-Objekt weiterhin initialisieren, erhalten Sie die meiste Zeit die gleiche Nummer.

4

Das Mischen funktioniert so schnell, dass es zwischen zwei Aufrufen von Random.NEXT() KEINE MS-Verzögerung gibt, die zu nicht annähernd zufälligem Verhalten führt.

Was macht Sie denken, dass es eine ms Verzögerung zwischen zwei Anrufen zu Random.Next sein muss?

Ihr Bog Standard-Zufallszahlengenerator wird einige Initial Seed nehmen (sagen wir die Systemuhr) und dann wiederholt einige Algorithmen zu diesem Seed, um eine Folge von Zahlen zu erzeugen, die zufällig erscheint. Die meisten dieser Algorithmen verwenden die Uhr nicht als Eingabe für den Seed und es ist daher egal, wie schnell zwei aufeinanderfolgende Aufrufe ausgeführt werden.

Der Grund Code fehlschlägt, weil Sie es nicht bei jeder Iteration einen neuen Zufallszahlengenerator instanziieren. Dies ist, wo die Uhr dich töten kann, weil du am Ende zweimal mit dem gleichen Samen kommst. Sie rufen nicht Random.Next nacheinander auf dem gleichen Zufallszahlengenerator. Sie rufen Random.Next auf einen neuen Zufallszahlengenerator bei jeder Iteration und manchmal diese Zufallszahlengeneratoren sind mit dem gleichen Wert ausgesät, weil man sich durch den Systemtakt säen.

Bewegen Sie die Instanziierung des Zufallszahlengenerators außerhalb Ihrer Schleife.

var resultA = new List<int>(); 
Random rg = new Random(); 
for (int i = 0; i < 1000; i++) { 
    resultA.Add(rg.Next(5)); 
} 
+0

Es ist, weil er immer neue Randoms in seinem Code –

+5

@abelenky erstellt: Wenn ich -1 Ihr Kommentar für meine Antwort nicht lesen könnte, würde ich. – jason

+0

können Sie es als Noise/Offensive/Spam markieren – KevinDTimm

Verwandte Themen