boost::random vs andere MersenneTwister Implementation
-
Folgende Code-Beispiele zuerst:
Boost:
boost::uniform_real<> distance(min, max); boost::variate_generator<boost::rand48&, boost::uniform_real<> > dice(m_rand, distance); return dice();Ergebnis: http://www.abload.de/img/boost_randzzhg.png
Alternative mt19937 Implementation:
int r = (m_rand2.randInt()%(max-min))+min; return r;Ergebnis: http://www.abload.de/img/mtrandlzbo.png
Die zweite Implementation erzeugt definitiv bessere Ergebnisse.
Mein Fehler oder woran liegt das?
Die Frage stelle ich deswegen, weil die 2te Implementation etwas langsamer ist.
Das Ergebnis gefällt mir aber weit besser.Zur Erklärung: Die Sprite Positionen werden über den Zufallszahlen Generator erzeugt.
Bei beiden Versuchen wurde das Random-Objekt (die Klasse) wiederverwendet.
Beide bekamen den selben Seed:int seed = timeGetTime();edit: Jetzt habe ich im obigen Beispiel aus Versehen noch den rand48 drin als Generator, aber ich habs mit boost::mt19937 genauso versucht und das gleiche Ergebnis. Was mich btw sehr verwundert. Sollten 2 versch. Generatoren nicht unterschiedliche Ergebnisse produzieren?
-
Bist du denn sicher, daß du die Generatoren nur ein mal initialisiert hast?
(PS: boost::rand48 ist kein Mersenne-Twister

-
Ja, nur einmal initialisiert.
Im Konstruktor eines Singletons (das einzige in meinem Programm).Zum Code:
Ja, hab aus versehen den rand48() Code kopiert.boost::uniform_real<> distance(min, max); boost::variate_generator<boost::mt19937&, boost::uniform_real<> > dice(m_rand, distance); return dice();Das wäre der richtige.
-
Okay, nach einem Neustart schauts so aus:
http://www.abload.de/img/boost_rand2e7ra.png
Mit dem boost::mt19937.
Ahjo, ich beobachte das mal weiter. Ich werd erstmal bei der boost version bleiben, weil die ist deutlich schneller.
-
Hast du mal versucht, auch den variate_generator<> in deinem Singleton anzulegen?
-
CStoll schrieb:
Hast du mal versucht, auch den variate_generator<> in deinem Singleton anzulegen?
Probiert ja, aber das geht nicht.
Visual C++ 2008 Prof. schrieb:
Error 1 error C2512: 'boost::variate_generator<Engine,Distribution>' : no appropriate default constructor available d:\Source\NightLight2D\NightLightDLL\NLSystemController.cpp 49 NightLightDLL
Error 4 error C2582: 'operator =' function is unavailable in 'boost::variate_generator<Engine,Distribution>' d:\Source\NightLight2D\NightLightDLL\NLSystemController.cpp 265 NightLightDLLNaja, bisher ist das Ergebnis stabil.
Keine Ahnung ehrlich gesagt. Und ich hatte mit rand48 und boost::mt19937 wie gesagt das gleiche Ergebnis. Bzw seehr ähnlich dass alle Sprites in diesem schrägen Winkel angeordnet wurden.
Das jetzige Ergebnis ist in Ordnung, das gefällt mir. Ist auch besser als die andere mt19937-Implementation vom Ergebnis her. Mehr noise, wenn man das so nennen kann.
-
Scorcher24 schrieb:
Das jetzige Ergebnis ist in Ordnung, das gefällt mir. Ist auch besser als die andere mt19937-Implementation vom Ergebnis her. Mehr noise, wenn man das so nennen kann.
Das kann eigentlich nicht sein (es sei denn eine der beiden Implementierungen ist fehlerhaft). Jede (korrekte) MT-19937 Implementierung muss bei gleichem Seed die gleichen Zahlen erzeugen.
-
// MersenneTwister.h
// Mersenne Twister random number generator -- a C++ class MTRand
// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com// The Mersenne Twister is an algorithm for generating random numbers. It
// was designed with consideration of the flaws in various other generators.
// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
// are far greater. The generator is also fast; it avoids multiplication and
// division, and it benefits from caches and pipelines. For more information
// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html// Reference
// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
// Copyright (C) 2000 - 2003, Richard J. Wagner
// All rights reserved.Das ist die "andere" Implementation von der ich sprach.
Und ja, sorry, ich kann auch nix dafür....
-
hustbaer schrieb:
Scorcher24 schrieb:
Das jetzige Ergebnis ist in Ordnung, das gefällt mir. Ist auch besser als die andere mt19937-Implementation vom Ergebnis her. Mehr noise, wenn man das so nennen kann.
Das kann eigentlich nicht sein (es sei denn eine der beiden Implementierungen ist fehlerhaft). Jede (korrekte) MT-19937 Implementierung muss bei gleichem Seed die gleichen Zahlen erzeugen.
Was eventuell einen Unterschied bewirken könnte, ist die Nachbehandlung der ermittelten Zufallszahlen durch die Distribution (bei Boost) bzw. die Modulo-Konstruktion. Der uniform_real<> arbeitet mit double-Werten und liefert dadurch auch Zwischenwerte (ja, ich habe mir extra für dich die Header von Boost angesehen).
-
Wenn Du beim Platzieren von Sprites solche Muster siehst, dann ist was ganz anderes faul. Auch mit std::rand darf das nicht passieren.
-
volkard schrieb:
Wenn Du beim Platzieren von Sprites solche Muster siehst, dann ist was ganz anderes faul. Auch mit std::rand darf das nicht passieren.
Kann das daran liegen, dass ich meine Maschine teilweise tagelang laufen habe und nur Hybernate nutze und nicht ganz abschalte?
Weil timeGetTime() gibt ja die ms zurück seit das System gestartet wurde.
Und die nutzte ich als Seed. Habe das jetzt mal in std::time(NULL) geändert.
Wie gesagt, seit nem Neustart tritt das nicht mehr auf.Das ist jetzt mein fertiger Code:
class NLSystemController { /* [....] */ typedef boost::mt19937 TRandomGenerator; typedef boost::uniform_int<> TRandomIntUniform; typedef boost::variate_generator<TRandomGenerator&, TRandomIntUniform > TIntVariateGen; TRandomGenerator m_rand; }; NLSystemController::NLSystemController() : m_logbook(NULL), m_window(NULL) { /* .... */ m_rand.seed(static_cast<int>(std::time(NULL))); } int NLSystemController::getRandomNumber( int min, int max ) { TRandomIntUniform distance(min, max); TIntVariateGen dice(m_rand, distance); return dice(); } int NLSystemController::getRandomNumber() { TRandomIntUniform distance; TIntVariateGen dice(m_rand, distance); return dice(); }