Zufallszahlen generieren mit std::generate -> immer die gleichen Zahlen
-
Hi Forum,
ich habe folgenden C++ Code im Forum gefunden und nach meinen Wuenschen modifiziert:
boost::dynamic_bitset<> generate(boost::dynamic_bitset<>::size_type n) { static std::random_device rd; const int bpb = boost::dynamic_bitset<>::bits_per_block; std::vector<boost::dynamic_bitset<>::block_type>arr; arr.resize(n%bpb ? n/bpb+1 : n/bpb); static std::independent_bits_engine<std::minstd_rand, boost::dynamic_bitset<>::bits_per_block, boost::dynamic_bitset<>::block_width_type> engine(rd); std::generate(std::begin(arr), std::end(arr), engine); boost::dynamic_bitset<> ret(std::begin(arr), std::end(arr)); return ret; }Jedoch werden immer die gleichen Zahlen generiert, wenn ich die Zeile std::generate mit folgender ersetze, geht es auf einmal:
for(auto i=arr.begin();i!=arr.cend();i++) (*i) = engine();Warum funktioniert es nicht mit std::generate?
Vielen Dank fuer eure Hilfe
-
Erstens: Das sieht verdächtig nach meinem Code aus, ich erinnere mich nur nicht woher... ahh, von hier: http://www.c-plusplus.net/forum/317308-full
Zweitens: Der gezeigte Code funktioniert gar nicht. Es funktioniert, wenn du es so umschreibst*:
boost::dynamic_bitset<> generate(boost::dynamic_bitset<>::size_type n) { const int bpb = boost::dynamic_bitset<>::bits_per_block; std::vector<boost::dynamic_bitset<>::block_type> arr(n%bpb ? n/bpb+1 : n/bpb); // Siehe Link, lässt sich abkürzen static std::independent_bits_engine<std::minstd_rand, boost::dynamic_bitset<>::bits_per_block, boost::dynamic_bitset<>::block_width_type> engine; std::generate(std::begin(arr), std::end(arr), engine); // Hmm. Vielleicht std::ref, gehts bei dir dann? boost::dynamic_bitset<> ret(std::begin(arr), std::end(arr)); return ret; }Und wenn du meinen mit deinem vergleichst, siehst du, dass ich seede.
Mitstd::generatehat das nichts zu tun - Schleifenversion undgenerateproduzieren auf meinem Rechner gleiche Bits.static std::independent_bits_engine<std::minstd_rand, boost::dynamic_bitset<>::bits_per_block, boost::dynamic_bitset<>::block_width_type> engine( std::chrono::system_clock::now().time_since_epoch().count() ); // list-initialization mal weggelassen, führt hier zu narrowing*Edit: Ok, ja, du hast ein Klammerpaar vergessen, dann geht auch die Version aus deinem Post (du seedest). Allerdings selbes Ergebnis bei mir: Sowohl Schleife als auch
generatebringen gleiche Ergebnisse. Es liegt nur am Seed.
-
Wie kann ich dann die std::random_device rd zum seeden benutzen?
Wenn ich schreibe:
static std::independent_bits_engine<std::minstd_rand, boost::dynamic_bitset<>::bits_per_block, boost::dynamic_bitset<>::block_width_type> engine{ rd };kompiliert VC++ 2010 nicht, die {} Klammern mag er nicht?
-
Ja, wenn ich std::ref nehme:
std::generate(arr.begin(), arr.end(),std::ref(engine));Dann geht es. Aber wieso muss man an dieser Stelle std::ref verwenden?
-
Wie kann ich dann die std::random_device rd zum seeden benutzen?
Das solltest du gar nicht. Nimm einfach meine Version.
random_deviceist auch laut Standard nicht verpflichtet, bei jedem Programmablauf neue Zahlen zu erzeugen.If implementation limitations prevent generating non-deterministic random numbers, the implementation may employ a random number engine.
Die geschweiften Klammern sind ein C++11-feature, genannt list-initialization.
-
(Doppelpost)
-
Danke fuer die Hilfe und Hinweise! Aber warum geht es nur mit std::ref?
-
Random_1337 schrieb:
Danke fuer die Hilfe und Hinweise! Aber warum geht es nur mit std::ref?
Weil so nicht kopiert wird, das war eigentlich nur geraten von mir...
-
Sone schrieb:
random_deviceist auch laut Standard nicht verpflichtet, bei jedem Programmablauf neue Zahlen zu erzeugen.If implementation limitations prevent generating non-deterministic random numbers, the implementation may employ a random number engine.
Zu beschreiben was daran Quark ist und wieso genau ist hoffentlich etwas was ich nicht tun muss, oder?
-
Random_1337 schrieb:
Danke fuer die Hilfe und Hinweise! Aber warum geht es nur mit std::ref?
std::generatenimmt den Generator "by value" - wie es in der STL mit Funktoren üblich ist. D.h. er wird kopiert, und dadurch bleibt das Original unverändert.