Warum liefert rand() bei jedem Durchlauf dieselbe Zahlenfolge?

Lesezeit: 6 Minuten

Warum liefert rand bei jedem Durchlauf dieselbe Zahlenfolge
Patrick Lorio

Jedes Mal, wenn ich ein Programm mit starte rand() es gibt mir die gleichen Ergebnisse.

Beispiel:

#include <iostream>
#include <cstdlib>

using namespace std;

int random (int low, int high) {
    if (low > high)
        return high;
    return low + (rand() % (high - low + 1));
}

int main (int argc, char* argv []) {
    for (int i = 0; i < 5; i++)
        cout << random (2, 5) << endl;
}

Ausgabe:

3
5
4
2
3

Jedes Mal, wenn ich das Programm starte, gibt es jedes Mal die gleichen Zahlen aus. Gibt es eine Möglichkeit, dies zu umgehen?

Der Seed für den Zufallszahlengenerator ist nicht gesetzt.

Wenn Sie anrufen srand((unsigned int)time(NULL)) dann erhalten Sie zufälligere Ergebnisse:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand((unsigned int)time(NULL));
    cout << rand() << endl;
    return 0;
}

Der Grund ist, dass eine Zufallszahl aus der generiert wird rand() Funktion ist nicht wirklich zufällig. Es ist einfach eine Transformation. Wikipedia gibt eine bessere Erklärung der Bedeutung des Pseudozufallszahlengenerators: deterministischer Zufallsbitgenerator. Jedes Mal, wenn Sie anrufen rand() Es nimmt den Seed und/oder die letzte(n) generierte(n) Zufallszahl(en) (der C-Standard gibt den verwendeten Algorithmus nicht an, obwohl C++11 Einrichtungen zum Angeben einiger gängiger Algorithmen hat), führt eine mathematische Operation mit diesen Zahlen aus und gibt das Ergebnis zurück. Wenn also der Seed-Status jedes Mal gleich ist (wie wenn Sie nicht anrufen srand mit einer echten Zufallszahl), dann erhalten Sie immer die gleichen ‘Zufallszahlen’.

Wenn Sie mehr wissen möchten, können Sie Folgendes lesen:

http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/

http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/

  • Was ist, wenn ich die Funktion in einer .h-Datei habe? Wo ist der geeignete Ort, um den Samen zu setzen, wenn nicht in der Hauptpflanze?

    – David Montgomery

    15. Mai 2019 um 18:34 Uhr

  • Sie könnten es im Konstruktor eines Objekts setzen, von dem Sie wissen, dass es vorher konstruiert wird rand() wird zuerst aufgerufen (z. B. in einem statischen/Singleton-Objekt, falls erforderlich)

    – Jeremy Friesner

    22. Dezember 2020 um 21:59 Uhr

Warum liefert rand bei jedem Durchlauf dieselbe Zahlenfolge
paxdiablo

Wenn Sie anrufen rand() ohne vorher anzurufen srand()wird es so tun, als ob Sie angerufen hätten srand(1) implizit. Das relevante Bit des Standards C99 7.20.2.2 The srand function (auf welche cstdlib basiert) heißt es:

Wenn rand aufgerufen wird, bevor Aufrufe an srand getätigt wurden, wird dieselbe Sequenz generiert wie beim ersten Aufruf von srand mit einem Startwert von 1.

Mit anderen Worten, Sie Wille erhalten Sie jedes Mal die gleiche Reihenfolge. Sie können Ihre ändern main hinein:

int main (int argc, char* argv []) {
    srand (time (0));  // needs ctime header.
    for (int i = 0; i < 5; i++)
        cout << random (2, 5) << endl;
    wait ();
}

um dies zu beheben, vorausgesetzt, Sie führen es nicht mehr als einmal pro Sekunde aus.

Wie bereits erwähnt, benötigen Sie die ctime Kopfzeile dazu. Du solltest auch einziehen cstdlib denn da ist es rand und srand lebend. Es ist normalerweise auch eine gute Idee, die zu verwenden cXXX Kopfzeilen statt der XXX.h Einsen (cmath eher, als math.hzum Beispiel).

Also gemacht alle Diese Änderungen (und die Verwendung expliziter Namespaces, die ich bevorzuge, andere möglicherweise nicht), würde ich am Ende erhalten:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>

void wait () {
    int e;
    std::cin >> e;
}

int random (int low, int high) {
    if (low > high) return high;
    return low + (std::rand() % (high - low + 1));
}

int main (int argc, char* argv []) {
    std::srand (std::time (0));
    for (int i = 0; i < 5; i++)
        std::cout << random (2, 5) << '\n';
    wait ();
}

was jedes Mal, wenn ich es ausführe, eine andere Sequenz ergibt, jedenfalls ein paar Mal. Offensichtlich gibt es eine feste Grenze dafür, wann sich die Daten wiederholen (es gibt nur 45 Möglichkeiten) und die “zufällige” Natur der Ausgabe bedeutet, dass sie sich auch vorher wiederholen kann 🙂

1646889007 667 Warum liefert rand bei jedem Durchlauf dieselbe Zahlenfolge
Sebastian Mach

Das ist ein Merkmal der rand() Funktion.

Was Sie haben, ist kein Zufallszahlengenerator, sondern genauer gesagt ein “Pseudozufallszahlengenerator”. In der Lage zu sein, die gleichen zufälligen Sequenzen für den gleichen Seed zu reproduzieren (Sie Seed mit dem srand(x) Funktion) kann wichtig sein, um Fehler zu reproduzieren oder den Status über Programmläufe hinweg beizubehalten.

Persönlich verwende ich diese Funktion, um Rendering-Prozesse in a pausieren/beibehalten zu können Monte Carlo-basierter Terrain-Renderer. Ein netter Nebeneffekt ist, dass Sie unterschiedliche Monte-Carlo-Experimente auf verschiedenen Maschinen garantieren können und somit garantiert unterschiedliche Ergebnisse generieren können, die dann in einem letzten Schritt auf ein qualitativ hochwertigeres Endergebnis reduziert werden können (natürlich können Sie später wiederverwenden dieses qualitativ hochwertigere Endergebnis, um noch hochwertigere Ergebnisse zu erzielen).

Beachten Sie jedoch, dass weder C noch C++ die Zahlenfolge aus definieren rand(). Wenn Sie also plattformübergreifend garantierte Sequenzen benötigen, verwenden Sie einen der neuen Zufallszahlengeneratoren von C++11 (z Mersenne-Twister), rollen Sie Ihre eigenen (einige Generatoren sind jedoch fast trivial zu verstehen, da die meisten von ihnen auf ein bestimmtes Überlaufverhalten angewiesen sind, ist ihre Implementierung möglicherweise nicht trivial) oder verwenden Sie eine Komponente eines Drittanbieters (z. B. boost::random).

Sie müssen den Zufallszahlengenerator sättigen (siehe die Funktion ‘srand’). Angenommen, Sie machen keine Kryptografie, dann ist es wahrscheinlich gut genug, sie mit der Ausgabe von „time“ zu versehen.

Sie erhalten tatsächlich Pseudo-Zufallszahlen. Um sie “zufälliger” zu machen, können Sie den Zufallszahlengenerator mit etwas “verändern” (am häufigsten die aktuelle Zeit) füttern.

  • Nit: Mathematisch gesehen werden sie dadurch nicht “zufälliger”.

    – Sebastian Mach

    27. Februar 2012 um 10:51 Uhr

  • Stimmt, aber im Zusammenhang mit der Frage des OP … (und es steht in Anführungszeichen 😉

    – John3136

    27. Februar 2012 um 23:48 Uhr

1646889008 36 Warum liefert rand bei jedem Durchlauf dieselbe Zahlenfolge
H98

C++ verwendet einen Pseudozufallszahlengenerator. Im Wesentlichen bedeutet dies, dass Ihr Programm eine extrem lange Liste vorgegebener Zahlen vorliest. Wenn Sie Ihr Programm wiederholt ausführen, gibt es jedes Mal die gleichen Zahlen aus, weil es jedes Mal vom Anfang dieser Liste von Zahlen liest.

Sie können Ihr Programm so einstellen, dass es bei der n-ten Nummer in der Liste beginnt. Sie können die Zeit oder die Temperatur oder irgendetwas anderes verwenden, das “zufällig” ist. (Für die Temperatur können Sie die letzte Ziffer der Temperatur nehmen oder die Dezimalstellen danach verwenden.)

  • Nit: Mathematisch gesehen werden sie dadurch nicht “zufälliger”.

    – Sebastian Mach

    27. Februar 2012 um 10:51 Uhr

  • Stimmt, aber im Zusammenhang mit der Frage des OP … (und es steht in Anführungszeichen 😉

    – John3136

    27. Februar 2012 um 23:48 Uhr

1646889008 187 Warum liefert rand bei jedem Durchlauf dieselbe Zahlenfolge
Peter Mortensen

Verwenden Sie randomize(). Der Wert wird automatisch gesät. Oder wenn Sie rand() verwenden möchten, können Sie es mit srand(seedvalue); Der Startwert kann so etwas wie die Systemzeit sein … das gibt Ihnen jedes Mal andere Zufallszahlen.

  • randomize ist keine C++-Standardfunktion. Von welcher Plattform sprichst du?

    – Sebastian Mach

    1. Februar 2015 um 9:33 Uhr

986320cookie-checkWarum liefert rand() bei jedem Durchlauf dieselbe Zahlenfolge?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy