Wie der Titel schon sagt, versuche ich, mithilfe der neuen C ++ 11- <random>
Bibliothek einen Weg zu finden, Zufallszahlen zu generieren . Ich habe es mit diesem Code versucht:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Das Problem mit dem Code, den ich habe, ist, dass jedes Mal, wenn ich ihn kompiliere und ausführe, immer die gleichen Zahlen generiert werden. Meine Frage ist also, welche anderen Funktionen in der Zufallsbibliothek dies erreichen können, während sie wirklich zufällig sind.
Für meinen speziellen Anwendungsfall habe ich versucht, einen Wert innerhalb des Bereichs zu erhalten [1, 10]
std::mt19937
als Motor zu verwenden, es sei denn, Sie haben einen guten Grund, dies nicht zu tun. Und die Verteilung ist an beiden Enden ein geschlossenes Intervall.std::uniform_int_distribution
, das an beiden Enden geschlossen ist .Antworten:
Stephan T. Lavavej (stl) von Microsoft hat bei Going Native einen Vortrag darüber gehalten, wie die neuen C ++ 11-Zufallsfunktionen verwendet werden und warum nicht
rand()
. Darin enthielt er eine Folie, die Ihre Frage im Grunde löst. Ich habe den Code von dieser Folie unten kopiert.Sie können seinen vollständigen Vortrag hier sehen: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Wir verwenden
random_device
einmal, um den genannten Zufallszahlengenerator zu setzenmt
.random_device()
ist langsamer alsmt19937
, muss aber nicht gesetzt werden, da zufällige Daten von Ihrem Betriebssystem angefordert werden (die von verschiedenen Orten stammen, wie z. B. RdRand ).Wenn Sie sich diese Frage / Antwort ansehen , wird anscheinend
uniform_real_distribution
eine Zahl in dem Bereich zurückgegeben[a, b)
, in dem Sie möchten[a, b]
. Um das zu tun, sollten unsereuniform_real_distibution
eigentlich so aussehen:quelle
default_random_engine
default_random_engine
.std::default_container
, hoffentlich gibt es keinen Menschen, die sich als Programmierer betrachten, die die Unterschiede nicht kennen, haben viele Skriptsprachen eine Standardstruktur für den Kartentyp, die auf eine Vielzahl von Arten implementiert werden kann, die der Benutzer möglicherweise nicht kenntnextafter
Anruf ist für die meisten Anwendungen übertrieben. Die Chancen einer zufälligendouble
Landung genau auf dem Endpunkt sind so gering, dass es keinen praktischen Unterschied zwischen Einschließen und Ausschließen gibt.std::vector
nicht Analogie hier nicht arbeiten , weilstd::vector
ist wegen CPU - Caching eigentlich ein guter Standard. Es ist sogar besserstd::list
als das Einsetzen in die Mitte. Dies gilt auch dann, wenn Sie alle Container verstehen und aufgrund der algorithmischen Komplexität eine fundierte Entscheidung treffen können.Meine 'zufällige' Bibliothek bietet einen äußerst praktischen Wrapper für zufällige C ++ 11-Klassen. Sie können fast alle Dinge mit einer einfachen 'get'-Methode erledigen.
Beispiele:
Zufallszahl in einem Bereich
Zufälliger Boolescher Wert
Zufälliger Wert aus einer std :: initilizer_list
Zufälliger Iterator aus dem Iteratorbereich oder dem gesamten Container
Und noch mehr Dinge! Schauen Sie sich die Github-Seite an:
https://github.com/effolkronium/random
quelle
I rot all das Zeug oben, über 40 andere Seiten mit c ++ darin wie dieser und das beobachtete Video von Stephan T. Lavavej „STL“ und war immer noch nicht sicher , wie Zufallszahlen funktionieren in der Praxis , damit ich einen vollen Sonntag nahm , um herauszufinden , Worum geht es und wie es funktioniert und verwendet werden kann.
Meiner Meinung nach hat STL Recht damit, "srand nicht mehr zu verwenden", und er hat es im Video 2 gut erklärt . Er empfiehlt außerdem:
a)
void random_device_uniform()
- für verschlüsselte Erzeugung, aber langsamer (aus meinem Beispiel)b) die Beispiele mit
mt19937
- schneller, Fähigkeit, Samen zu erstellen, nicht verschlüsseltIch habe alle beanspruchten C ++ 11-Bücher herausgezogen, auf die ich Zugriff habe, und festgestellt, dass deutsche Autoren wie Breymann (2015) immer noch einen Klon von verwenden
nur mit
<random>
statt<time> and <cstdlib>
#includings - also sei vorsichtig, nur aus einem Buch zu lernen :).Bedeutung - das sollte seit c ++ 11 nicht mehr verwendet werden, weil:
Ich fand schließlich die beste Erklärung aus 20 Büchern in Bjarne Stroustrups neueren - und er sollte sich damit auskennen - in "Eine Tour durch C ++ 2019", "Programmierprinzipien und Übung mit C ++ 2016" und "The C ++ Programming Language 4th Edition" 2014 "und auch einige Beispiele in" Lippmans C ++ Primer fünfte Ausgabe 2012 ":
Und es ist wirklich einfach, weil ein Zufallszahlengenerator aus zwei Teilen besteht: (1) einer Engine, die eine Folge von Zufalls- oder Pseudozufallswerten erzeugt. (2) eine Verteilung, die diese Werte in eine mathematische Verteilung in einem Bereich abbildet.
Trotz der Meinung von Microsofts STL schreibt Bjarne Stroustrups:
Das
void die_roll()
Beispiel stammt von Bjarne Stroustrups - eine gute Idee, mit der Engine und Distribution generiert werdenusing
(mehr dazu hier) .Um die Zufallszahlengeneratoren, die von der Standardbibliothek hier bereitgestellt werden, in der Praxis nutzen zu können, wurde
<random>
hier ein ausführbarer Code mit verschiedenen Beispielen auf das Mindeste reduziert, was hoffentlich Zeit und Geld für Sie sicher macht:Ich denke, das summiert sich auf alles und wie gesagt, ich habe eine Menge gelesen und Zeit gebraucht, um diese Beispiele zu destillieren. Wenn Sie weitere Informationen zur Zahlengenerierung haben, freue ich mich, dies per PM oder im Kommentarbereich zu erfahren und wird es bei Bedarf hinzufügen oder diesen Beitrag bearbeiten. Bool
quelle
Hier ist etwas, das ich gerade in diese Richtung geschrieben habe:
~
quelle
Hier ist eine Ressource, die Sie über den Pseudozufallszahlengenerator lesen können.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
Grundsätzlich benötigen Zufallszahlen im Computer einen Startwert (diese Zahl kann die aktuelle Systemzeit sein).
Ersetzen
Durch
quelle
Sie haben zwei häufige Situationen. Das erste ist, dass Sie Zufallszahlen wollen und sich nicht zu sehr um die Qualität oder Ausführungsgeschwindigkeit kümmern. Verwenden Sie in diesem Fall das folgende Makro
das gibt Ihnen p im Bereich von 0 bis 1 - epsilon (es sei denn, RAND_MAX ist größer als die Genauigkeit eines Doppels, aber machen Sie sich darüber Sorgen, wenn Sie dazu kommen).
int x = (int) (uniform () * N);
Gibt nun eine zufällige ganze Zahl von 0 bis N -1 an.
Wenn Sie andere Distributionen benötigen, müssen Sie p transformieren. Oder manchmal ist es einfacher, uniform () mehrmals aufzurufen.
Wenn Sie wiederholbares Verhalten wünschen, setzen Sie mit einer Konstanten, andernfalls mit einem Aufruf von time ().
Wenn Sie sich jetzt Gedanken über Qualität oder Laufzeitleistung machen, schreiben Sie uniform () neu. Aber ansonsten berühren Sie den Code nicht. Halten Sie immer uniform () auf 0 bis 1 minus Epsilon. Jetzt können Sie die C ++ - Zufallszahlenbibliothek umbrechen, um eine bessere Uniform () zu erstellen. Dies ist jedoch eine Art Option auf mittlerer Ebene. Wenn Sie sich Gedanken über die Eigenschaften des RNG machen, lohnt es sich auch, ein wenig Zeit zu investieren, um zu verstehen, wie die zugrunde liegenden Methoden funktionieren, und dann eine bereitzustellen. Sie haben also die vollständige Kontrolle über den Code und können garantieren, dass die Reihenfolge mit demselben Startwert immer exakt gleich ist, unabhängig von der Plattform oder der Version von C ++, mit der Sie verknüpfen.
quelle