Ich sehe viele Antworten, in denen jemand vorschlägt <random>
, Zufallszahlen zu generieren, normalerweise zusammen mit Code wie diesem:
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 5);
dis(gen);
Normalerweise ersetzt dies eine Art "unheiligen Greuel" wie:
srand(time(NULL));
rand()%6;
Wir könnten den alten Weg kritisieren , indem wir argumentieren, dass er time(NULL)
eine niedrige Entropie liefert, time(NULL)
vorhersehbar ist und das Endergebnis ungleichmäßig ist.
Aber all das gilt für den neuen Weg: Er hat nur ein glänzenderes Furnier.
rd()
gibt eine einzelne zurückunsigned int
. Dies hat mindestens 16 Bit und wahrscheinlich 32. Das reicht nicht aus, um die 19937-Bit-Zustände von MT zu setzen.Die Verwendung
std::mt19937 gen(rd());gen()
(Seeding mit 32 Bit und Betrachten der ersten Ausgabe) ergibt keine gute Ausgabeverteilung. 7 und 13 können niemals die erste Ausgabe sein. Zwei Samen produzieren 0. Zwölf Samen produzieren 1226181350. ( Link )std::random_device
kann und wird manchmal als einfaches PRNG mit einem festen Startwert implementiert. Es kann daher sein, dass bei jedem Lauf dieselbe Sequenz erzeugt wird. ( Link ) Das ist noch schlimmer alstime(NULL)
.
Schlimmer noch, es ist sehr einfach, die oben genannten Codefragmente zu kopieren und einzufügen, trotz der darin enthaltenen Probleme. Einige Lösungen hierfür erfordern den Erwerb größerer Bibliotheken, die möglicherweise nicht für jeden geeignet sind.
Vor diesem Hintergrund lautet meine Frage: Wie kann man das mt19937 PRNG in C ++ kurz, portabel und gründlich aussäen?
Angesichts der oben genannten Probleme eine gute Antwort:
- Muss den mt19937 / mt19937_64 vollständig aussäen.
- Kann sich nicht nur auf
std::random_device
odertime(NULL)
als Entropiequelle verlassen. - Sollte sich nicht auf Boost oder andere Bibliotheken verlassen.
- Sollte in eine kleine Anzahl von Zeilen passen, so dass es gut aussehen würde, wenn es in eine Antwort eingefügt wird.
Gedanken
Mein aktueller Gedanke ist, dass Ausgaben von
std::random_device
(möglicherweise über XOR) mittime(NULL)
Werten, die aus der Adressraum-Randomisierung abgeleitet wurden , und einer fest codierten Konstante (die während der Verteilung festgelegt werden kann) kombiniert werden können , um eine bestmögliche Entropie zu erzielen.std::random_device::entropy()
gibt keinen guten Hinweis darauf, wasstd::random_device
tun könnte oder nicht.
std::random_device
, time(NULL)
und Funktionsadressen, dann XORed zusammen eine Art Best-Effort Entropiequelle zu erzeugen.
std::random_device
die Plattformen, auf denen Sie Ihr Programm ausführen möchten , ordnungsgemäß zu implementieren und eine Hilfsfunktion bereitzustellen, die einen Seed-Generator ( seed11::make_seeded<std::mt19937>()
) erstellt