Wie kurz und bündig, tragbar und gründlich Saatgut der mt19937 PRNG?

Scheine ich zu sehen, viele Antworten, in denen jemand schlägt mit <random> um Zufallszahlen zu generieren, in der Regel zusammen mit code wie diesem:

std::random_device rd;  
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 5);
dis(gen);

In der Regel ersetzt eine Art von "unholy abomination" wie:

srand(time(NULL));
rand()%6;

Könnten wir kritisieren der alten Weise, mit dem argument, dass time(NULL) bietet niedrige Entropie time(NULL) ist vorhersehbar, und das Ergebnis ist nicht einheitlich.

Aber das ist alles richtig und einen neuen Weg: es muss nur ein glänzender Furnier.

  • rd() gibt eine einzelne unsigned int. Dieser ist mindestens 16 bit und vermutlich 32. Das ist nicht genug, um die Samen MT 19937 bits des Staates.
  • Mit std::mt19937 gen(rd());gen() (seeding mit 32 bits und einem Blick auf die erste Ausgabe) nicht geben einen guten Ausgang Verteilung. 7 und 13 kann nie die erste Ausgabe. Zwei Samen produzieren 0. Zwölf Samen produzieren 1226181350. (Link)
  • std::random_device werden kann, und manchmal ist, implementiert als einfache PRNG mit einer festen Samen. Es könnte daher produzieren die gleiche Sequenz auf jedem Lauf. (Link) Das ist noch schlimmer als time(NULL).

Schlimmer noch, es ist sehr einfach zu kopieren und fügen Sie den vorangegangenen code-snippets, trotz der Probleme, die Sie enthalten. Einige Lösungen, die diese erfordern den Erwerb groessere Bibliotheken, die möglicherweise nicht geeignet für alle.

In diesem Licht, meine Frage ist Wie kann man kurz und bündig, tragbar und gründlich Saatgut der mt19937 PRNG in C++?

Angesichts der vorstehenden Probleme, eine gute Antwort:

  • Muss voll Samen der mt19937/mt19937_64.
  • Nicht allein auf std::random_device oder time(NULL) als Quelle der Entropie.
  • Sollte sich nicht darauf verlassen, Boost oder anderen libaries.
  • Sollte passen in eine kleine Anzahl von Linien, so dass es schön Aussehen würde, kopieren-einfügen in eine Antwort.

Gedanken

  • Mein Aktueller Gedanke ist, dass Ausgänge von std::random_device können püriert bis (vielleicht über XOR) mit time(NULL) Werte abgeleitet aus address space randomization, und eine hart codierte Konstante (die festgelegt werden konnte, bei der Verteilung) um einen best-effort-Schuss an Entropie.
  • std::random_device::entropy() nicht einen guten Anhaltspunkt geben, was std::random_device könnte oder nicht.
Was ist tragbare darüber? Dies ist eine C++ Frage, keine Linux-Frage.
Mein persönlicher Gedanke war, dass vielleicht die Werte konnten gezogen werden aus std::random_device, time(NULL) und Funktion-Adressen, dann XORed zusammen ergeben eine Art " best-effort-Entropie-Quelle.
Es wäre schön, wenn es die Funktion wie does_random_device_actually_work (), so könnte man zumindest ordnungsgemäß beeinträchtigen, oder produzieren Sie Warnungen oder Fehler für den Benutzer.
Die richtige Lösung ist nicht kurz, die kurze Lösung nicht richtig sein. Mein Ansatz verwende ich in meinem seed11 Bibliothek ist im Grunde zu implementieren std::random_device richtig auf den Plattformen Sie planen, führen Ihr Programm auf, und eine Hilfsfunktion, erzeugt einen gesetzten generator (seed11::make_seeded<std::mt19937>())
Beiseite: deine zweite Kugel etwas neues hinzufügen. Es ist nicht verwunderlich, dass Sie einen gewissen Wert, erscheint 12-mal. Sie sollten erwarten, dass es nur über drei Werte, die erscheinen genau 12-mal, unter der Annahme, dass du 2^32 independent, einheitlich random Beispiele.

InformationsquelleAutor Richard | 2017-07-12

Schreibe einen Kommentar