Gleiche Zufallszahlen bei jedem Schleifendurchlauf
Lesezeit: 4 Minuten
GlassZee
Ich habe ein for Schleife, die 15 Mal läuft, mit dh.setDoors() in jeder Iteration.
Was setDoors ruft an srand(time(0))dann wird immer dann, wenn eine Zufallszahl benötigt wird, verwendet, zum Beispiel carSetter = rand()%3+1. Alternativ kann es verwendet werden decider = rand()%2+1.
Jetzt normal decider und carSetter unterschiedlich verwendet werden, aber ich vermutete ein Problem und ließ es ausdrucken carSetter und decider bei jeder Iteration. Folgendes kam dabei heraus:
Door 1 has car
Decider is 2
Door 1 has car
Decider is 2
Door 1 has car
Decider is 2
Door 1 has car
Decider is 2
Door 1 has car
Decider is 2
etc...
Die Werte ‘1’ und ‘2’ ändern sich, wenn ich es mehrmals ausführe, sind aber während der 15 Male immer noch gleich.
Da die Schleife 15 verschiedene Male ausgeführt wird, sollte dies nicht der Fall sein carSetter und decider bei jeder Iteration eine andere Zufallszahl ausdrucken?
Wenn ich nicht habe srand(time(0))es funktioniert wie erwartet, aber es gibt kein Seed-Set, also ist es jedes Mal dieselbe Folge von “Zufallszahlen”, also ist es wahrscheinlich ein Problem mit dem Seed?
Die Aussaat sollte erfolgen Einmal, je. Informieren Sie sich darüber, wie Pseudozufallszahlengeneratoren funktionieren, und es ist wahrscheinlich gut, auch etwas Wahrscheinlichkeitstheorie zu lernen, während Sie dabei sind.
– Kerrek SB
12. Februar 2012 um 17:52 Uhr
Ich verwende srand nur einmal in setDoors, setDoors wird nur 15 Mal wiederholt. Ist das Problem, dass srand 15 Mal wiederholt wird?
– GlassZee
12. Februar 2012 um 17:55 Uhr
@GlassZee: Ja. Wie Kerrek bereits sagte, sollten Sie das tun srand einmal in Ihrem Programm.
– Leichtigkeitsrennen im Orbit
12. Februar 2012 um 17:56 Uhr
@GregHewgill: … das heißt, die tatsächlich Vervollständigen Sie den minimalen Testfall, mit dem das OP debuggt.
– Leichtigkeitsrennen im Orbit
12. Februar 2012 um 17:59 Uhr
Ein Kommentar zum Stil: Sie verwenden 0 als Zeigerwert in time(0). In modernem C++, insbesondere mit C++11, ist es eine schlechte Idee, es zu verwenden 0 als Zeiger. Verwenden nullptr wenn die Compiler, auf die Sie abzielen, dies unterstützen: srand(time(nullptr)). Wenn der Compiler nicht unterstützt nullptr dann NULL ist zumindest eine kleine Verbesserung gegenüber 0. Auch der <random> Die Bibliothek ist großartig, obwohl sie vielleicht ein bisschen über einen Studenten der ersten Woche hinausgeht.
– Namen53
12. Februar 2012 um 22:28 Uhr
Greg Hewgill
Wenn du anrufst srand(x)dann der Wert von x bestimmt die Folge von Pseudo-Zufallszahlen, die bei folgenden Aufrufen an zurückgegeben werden rand(), hängt ganz vom Wert ab x.
Wenn Sie in einer Schleife sind und anrufen srand() oben:
while (...) {
srand(time(0));
x = rand();
y = rand();
}
dann ist die gleich Abhängig vom Wert wird eine Zufallszahlenfolge generiert time(0) kehrt zurück. Da Computer schnell sind und Ihre Schleife wahrscheinlich in weniger als einer Sekunde läuft, time(0) gibt die zurück gleich Wert jedes Mal durch die Schleife. Damit x und y wird bei jeder Iteration gleich sein.
Stattdessen müssen Sie in der Regel nur anrufen srand()Einmal zu Beginn Ihres Programms:
srand(time(0));
while (...) {
x = rand();
y = rand();
}
Im oben genannten Fall x und y jedes Mal durch die Schleife unterschiedliche Werte haben.
Zieh meine blauen Pseudoschuhe an…
– Kerrek SB
12. Februar 2012 um 18:19 Uhr
Jedes Mal, wenn Sie aufrufen srand(time(0))du bist Aussaat den Pseudo-Zufallszahlengenerator, der ihn mit einer neuen Pseudo-Zufallszahlenfolge durchdringt. Die Reihenfolge ist unterschiedlich, je nachdem, wozu das Argument dient srand ist, und in diesem Fall verwenden Sie time(0) Wenn Sie also Ihr Programm höchstens einmal pro Sekunde aufrufen, erhalten Sie immer eine neue Sequenz. Wenn du anrufst rand()erhalten Sie nur die nächste Zahl in dieser Sequenz.
Da haben Sie sich jedoch für einen Anruf entschieden srand mehrmals in Ihrem Programm und weil Ihr Programm schnell ist (d. h time(0) ändert sich nicht), alles, was Sie tun, ist, den PRNG wiederholt auf dieselbe Sequenz zurückzusetzen. Aus diesem Grund erhalten Sie immer die gleichen Werte – Sie setzen den PRNG immer wieder neu auf dieselbe Sequenz, und dies bewegt auch den Cursor an den Anfang der Sequenz.
Einmal säen. Einmal.
Wie Kerrek sagte, wird das Seeding nur einmal am Anfang des Programms durchgeführt. Nach einem srand call rand so oft du willst.
Magnus Hof
Du musst laufen srand am Anfang Ihres Programms, zum Beispiel in der main-Funktion.
Wenn du rennst srand(time(0)) oben in der Funktion, die Sie verwenden rand()werden Sie ihm wahrscheinlich jedes Mal denselben Samen geben. time(0) gibt die Zeit in Sekunden an, Sie müssten also vermeiden, anzurufen setDoors zweimal innerhalb derselben Sekunde, um jedes Mal unterschiedliche Zahlen zu erhalten. Wenn du tun Anruf setDoors zweimal innerhalb derselben Sekunde, wird der Zufallsstartwert derselbe sein, und nachfolgende Aufrufe an rand() erzeugt die gleiche Folge von Pseudozufallszahlen.
9235500cookie-checkGleiche Zufallszahlen bei jedem Schleifendurchlaufyes
Die Aussaat sollte erfolgen Einmal, je. Informieren Sie sich darüber, wie Pseudozufallszahlengeneratoren funktionieren, und es ist wahrscheinlich gut, auch etwas Wahrscheinlichkeitstheorie zu lernen, während Sie dabei sind.
– Kerrek SB
12. Februar 2012 um 17:52 Uhr
Ich verwende srand nur einmal in setDoors, setDoors wird nur 15 Mal wiederholt. Ist das Problem, dass srand 15 Mal wiederholt wird?
– GlassZee
12. Februar 2012 um 17:55 Uhr
@GlassZee: Ja. Wie Kerrek bereits sagte, sollten Sie das tun
srand
einmal in Ihrem Programm.– Leichtigkeitsrennen im Orbit
12. Februar 2012 um 17:56 Uhr
@GregHewgill: … das heißt, die tatsächlich Vervollständigen Sie den minimalen Testfall, mit dem das OP debuggt.
– Leichtigkeitsrennen im Orbit
12. Februar 2012 um 17:59 Uhr
Ein Kommentar zum Stil: Sie verwenden
0
als Zeigerwert intime(0)
. In modernem C++, insbesondere mit C++11, ist es eine schlechte Idee, es zu verwenden0
als Zeiger. Verwendennullptr
wenn die Compiler, auf die Sie abzielen, dies unterstützen:srand(time(nullptr))
. Wenn der Compiler nicht unterstütztnullptr
dannNULL
ist zumindest eine kleine Verbesserung gegenüber0
. Auch der<random>
Die Bibliothek ist großartig, obwohl sie vielleicht ein bisschen über einen Studenten der ersten Woche hinausgeht.– Namen53
12. Februar 2012 um 22:28 Uhr