Generieren Sie zufällige Zahlen mit zufälliger C ++ 11-Bibliothek

Wie der Titel andeutet, versuche ich herauszufinden, wie man mit der neuen C ++ 11 -Bibliothek . Ich habe es mit diesem Code versucht:

 std::default_random_engine generator; std::uniform_real_distribution uniform_distance(1, 10.001); 

Das Problem mit dem Code, den ich habe, ist, dass jedes Mal, wenn ich es kompiliere und ausführe, es immer die gleichen Zahlen erzeugt. Also meine Frage ist, was andere functionen 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 [1, 10]

Stephan T. Lavavej (stl) von Microsoft hielt einen Vortrag bei Going Native über die Verwendung der neuen zufälligen C ++ 11-functionen und warum nicht rand() . Darin hat er eine Folie eingefügt, die im Grunde Ihre Frage triggers. Ich habe den Code von dieser Folie kopiert.

Sie können seine vollständige Rede hier sehen: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

 #include  #include  int main() { std::random_device rd; std::mt19937 mt(rd()); std::uniform_real_distribution dist(1.0, 10.0); for (int i=0; i<16; ++i) std::cout < < dist(mt) << "\n"; } 

Wir verwenden random_device einmal, um den Zufallszahlengenerator mt zu säen. random_device() ist langsamer als mt19937 , aber es muss nicht gesetzt werden, da es zufällige Daten von Ihrem Betriebssystem anfordert (die von verschiedenen Orten stammen, wie zum Beispiel RdRand ).


Wenn Sie diese Frage / Antwort betrachten , scheint uniform_real_distribution eine Zahl im Bereich [a, b] [a, b) , wo Sie [a, b] möchten. Um dies zu tun, sollte unsere uniform_real_distibution tatsächlich so aussehen:

 std::uniform_real_distribution dist(1, std::nextafter(10, DBL_MAX)); 

Meine ‘zufällige’ Bibliothek bietet einen sehr praktischen Wrapper für C ++ 11 zufällige classn. Sie können fast alle Dinge mit einer einfachen “Get” -Methode machen.

Beispiele:

  1. Zufallszahl in einem Bereich

     auto val = Random::get(-10, 10); // Integer auto val = Random::get(10.f, -10.f); // Float point 
  2. Zufälliger Boolscher Wert

     auto val = Random::get( ) // 50% to generate true auto val = Random::get( 0.7 ) // 70% to generate true 
  3. Zufälliger Wert aus einer std :: initiilizer_list

     auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or... 
  4. Zufälliger Iterator vom Iterator-Bereich oder vom gesamten Container

     auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator auto it = Random::get( vec ); // return random iterator 

Und noch mehr Dinge! Schauen Sie sich die github-Seite an:

https://github.com/effoltronium/random

Hier ist etwas, das ich gerade in diese Richtung geschrieben habe:

 #include  #include  #include  using namespace std; //============================================================== // RANDOM BACKOFF TIME //============================================================== class backoff_time_t { public: random_device rd; mt19937 mt; uniform_real_distribution dist; backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {} double rand() { return dist(mt); } }; thread_local backoff_time_t backoff_time; int main(int argc, char** argv) { double x1 = backoff_time.rand(); double x2 = backoff_time.rand(); double x3 = backoff_time.rand(); double x4 = backoff_time.rand(); return 0; } 

~

Sie haben zwei häufige Situationen. Das erste ist, dass Sie Zufallszahlen wollen und nicht zu sehr auf die Qualität oder Ausführungsgeschwindigkeit angewiesen sind. Verwenden Sie in diesem Fall das folgende Makro

 #define uniform() (rand()/(RAND_MAX + 1.0)) 

das gibt Ihnen p im Bereich von 0 bis 1 – Epsilon (es sei denn, RAND_MAX ist größer als die Genauigkeit eines Doppelten, aber machen Sie sich darüber Sorgen, wenn Sie dazu kommen).

int x = (int) (gleichförmig () * N);

Jetzt gibt es eine zufällige ganze Zahl von 0 bis N -1.

Wenn Sie andere Distributionen benötigen, müssen Sie p transformieren. Manchmal ist es auch einfacher, uniform () mehrmals aufzurufen.

Wenn Sie wiederholbares Verhalten wollen, säen Sie mit einer Konstante, ansonsten säen Sie mit einem Aufruf an die Zeit ().

Jetzt, wenn Sie über Qualität oder Laufzeit performance gestört sind, schreiben Sie einheitlich (). Aber berühren Sie den Code nicht. Halte immer uniform () auf 0 bis 1 minus epsilon. Jetzt können Sie die C ++ – Zufallszahlenbibliothek einbinden, um eine bessere Uniform () zu erstellen, aber das ist eine Art von Option auf mittlerer Ebene. Wenn Sie sich über die Eigenschaften des Zufallszahlengenerators Gedanken machen, dann lohnt es sich auch, etwas Zeit zu investieren, um zu verstehen, wie die zugrunde liegenden Methoden funktionieren, und dann einen zu liefern. So haben Sie die vollständige Kontrolle über den Code und Sie können garantieren, dass die Sequenz mit demselben Seed immer genau gleich ist, unabhängig von der Plattform oder der Version von C ++, mit der Sie verlinken.