Mehrere Zufallszahlen erzeugen
-
Hallo,
ich habe eine Frage zu Zufallszahlen. Wie solche in guter statistischer Qualität in modernem C++ erzeugen kann, findet man ja recht einfach bei Google, z.B so:
// Beispiel 1 #include <iostream> #include <random> int main() { std::random_device rd; std::mt19937 eng(rd()); std::uniform_real_distribution<double> dist(0, 1); for (int i = 1; i <= 10; ++i) std::cout << i << "\t" << dist(eng) << "\n"; // 10 random numbers }Soweit so gut, aber da braucht man drei Zeilen um lokale Variablen zu initialisieren, nur um eine Zufallszahl zu erzeugen.
Eine bequemere Methode (auch bei Google gefunden) wäre das in eine Funktion auszulagen, wie z.B. so:
// Beispiel 2 #include <iostream> #include <random> double rand_double(double min, double max) { std::uniform_real_distribution<double> dist(0, 1); static std::default_random_engine eng(std::random_device{}()); return dist(eng); } int main() { for (int i = 1; i <= 10; ++i) std::cout << i << "\t" << rand_double(0.0, 1.0) << "\n"; // 10 random numbers }Ist schonmal viel besser, aber meine Frage ist jetzt, wie sieht das aus wenn ich mehrere verschiedene Variablen zufällig erzeuge?
Dann verwenden die ja alle die selbestd::default_random_engine, kann das meine statistische Verteilung negativ beeinflussen (ich vermute schon)?Beispiel Code:
// Beispiel 3 #include <iostream> #include <random> double rand_double(double min, double max) { std::uniform_real_distribution<double> dist(0, 1); static std::default_random_engine eng(std::random_device{}()); return dist(eng); } int main() { for (int i = 1; i <= 10; ++i) { double x = rand_double(0.0, 1.0); double y = rand_double(0.0, 1.0); std::cout << i << "\t" << x << "\t" << y << "\n"; // 2 * 10 random numbers } }Für n Zufallszahlen müsste ich ja um eine gegenseitige Beeinflussung zu vermeiden auch n random_engines haben, die ich irgendwie "managen" muss.
Hier mal eine (sinnlose) Beispiel-Klasse:// Beispiel 4 #include <iostream> #include <random> struct Test { std::default_random_engine eng1, eng2, eng3; Test() : eng1((std::random_device{}())), eng2((std::random_device{}())), eng3((std::random_device{}())) {} double calculate() { std::uniform_real_distribution<double> dist(0, 1); double x1 = dist(eng1); double x2 = dist(eng2); double x3 = dist(eng3); return x1 + x2 + x3; } }; int main() { Test test; for (int i = 1; i <= 10; ++i) std::cout << i << "\t" << test.calculate() << "\n"; }So müsste es ja eigentlich "sicher" sein, also alle drei Zufallszahlen haben ihre eigene
random_engine.Frage: Kann man das auch einfacher machen?
Also die Einfachheit beim Aufruf wie in Beispiel 3 (ohne in jeder Klasse die Zufallszahlen verwenden will die engines "mitzuschleifen") aber trotzdem die Unabhängigkeit der Zahlen wie in Beispiel 4?Ich brauche relativ viele Zufallszahlen lokal, und eine einzige Funktion
rand_doubledie man einfach aufrufen kann ohne bei jeder neuen Variable wieder einen Member hinzufügen zu müssen wäre nicht schlecht.Geht das sinnvoll?
-
Ähm. Jo. Na. Geh mal lesen: http://www.pcg-random.org/posts/cpp-seeding-surprises.html