Angenommen, Sie möchten C ++ - Funktionen <random>
in einem praktischen Programm verwenden (für eine Definition von "praktisch" - die Einschränkungen hier sind Teil dieser Frage). Sie haben ungefähr folgenden Code:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
Meine Frage ist, für welchen Typ sollten Sie verwenden ENGINE
?
Ich habe immer gesagt,
std::mt19937
weil es schnell zu tippen war und eine Namenserkennung hatte. Aber heutzutage scheinen alle zu sagen, dass der Mersenne Twister sehr schwer und cache-unfreundlich ist und nicht einmal alle statistischen Tests besteht, die andere durchführen.Ich möchte sagen,
std::default_random_engine
weil es die offensichtliche "Standardeinstellung" ist. Aber ich weiß nicht, ob es von Plattform zu Plattform unterschiedlich ist. und ich weiß nicht, ob es statistisch etwas Gutes ist.Da jeder in diesen Tagen auf einer 64-Bit - Plattform ist, sollten wir zumindest sein mit
std::mt19937_64
überstd::mt19937
?Ich würde gerne sagen
pcg64
oderxoroshiro128
weil sie angesehen und leicht erscheinen, aber sie existieren nicht in<random>
überhaupt nicht.Ich weiß nichts über
minstd_rand
,minstd_rand0
,ranlux24
,knuth_b
etc. - sicher müssen sie für etwas gut sein?
Offensichtlich gibt es hier einige konkurrierende Einschränkungen.
Stärke des Motors. (
<random>
hat keine kryptografisch starken PRNGs, aber dennoch sind einige der standardisierten "schwächer" als andere, oder?)sizeof
der Motor.Geschwindigkeit seiner
operator()
.Einfache Aussaat.
mt19937
ist notorisch schwer richtig zu säen, weil es so viel Zustand zu initialisieren hat.Portabilität zwischen Bibliotheksanbietern. Wenn ein Anbieter
foo_engine
andere Nummern produziert als ein anderer Anbieterfoo_engine
, ist dies für einige Anwendungen nicht gut. (Hoffentlich schließt dies nichts aus, außer vielleichtdefault_random_engine
.)
Wenn Sie all diese Einschränkungen so gut wie möglich abwägen, was ist Ihrer Meinung nach die ultimative Antwort "Best Practice, innerhalb der Standardbibliothek zu bleiben"? Soll ich einfach weiter benutzen std::mt19937
oder was?
Antworten:
Die C ++ - Referenz listet alle zufälligen Engines auf, die derzeit von C ++ bereitgestellt werden. Die Auswahl der Motoren lässt jedoch zu wünschen übrig (siehe z. B. meine Liste hochwertiger Zufallsgeneratoren) ). Zum Beispiel:
default_random_engine
ist implementierungsdefiniert, daher ist nicht bekannt, ob die Engine statistische Fehler aufweist, die die Anwendung möglicherweise interessiert.linear_congruential_engine
implementiert lineare Kongruenzgeneratoren. Sie haben jedoch tendenziell eine schlechte Qualität, es sei denn, der Modul ist prim und sehr groß (mindestens 64 Bit). Außerdem können sie nicht mehr Samen als ihren Modul zulassen.minstd_rand0
undminstd_rand
nur etwa 2 ^ 31 Samen zugeben.knuth_b
Wraps aminstd_rand0
und mischt Bays-Durham davon.mt19937
undmt19937_64
könnten viel mehr Seeds zulassen, wenn sie besser initialisiert würden (z. B. durch Initialisieren von astd::seed_seq
mit mehreren Ausgaben vonrandom_device
nicht nur einer), aber sie verwenden ungefähr 2500 Bytes Status.ranlux24
undranlux48
verwenden ungefähr 577 Bit Status, aber sie sind langsam (sie arbeiten, indem sie einige beibehalten und andere pseudozufällige Ausgaben verwerfen).C ++ verfügt jedoch auch über zwei Engines, die eine andere Engine umschließen, um möglicherweise ihre Zufälligkeitseigenschaften zu verbessern:
discard_block_engine
verwirft einige der Ausgaben einer bestimmten zufälligen Engine.shuffle_order_engine
implementiert ein Bays-Durham-Shuffle einer bestimmten zufälligen Engine.Zum Beispiel ist es möglich, sagen wir, ein Bays-Durham shuffle zu haben
mt19937
,ranlux24
oder eine benutzerdefiniertelinear_congruential_engine
mitshuffle_order_engine
. Vielleicht ist der verpackte Motor von besserer Qualität als der ursprüngliche. Es ist jedoch schwierig, die statistische Qualität des neuen Motors ohne vorherzusagen testen .In Erwartung solcher Tests scheint dies
mt19937
die derzeit praktischste Engine im C ++ - Standard zu sein. Mir ist jedoch mindestens ein Vorschlag bekannt, zukünftigen Versionen von C ++ eine weitere Zufallszahlen-Engine hinzuzufügen (siehe C ++ - Papier P2075 ).quelle
Laut C ++ Referenz ,
default_random_engine
:Also für leichten Einsatz brauchen Sie sich keine Sorgen über alles, Samen zu sein
default_random_engine
mitEpoch Time (time(0))
und das wäre fein genug;)quelle