|
Pseudozufallszahlengeneratoren nichtkonstanter Wahrscheinlichkeitsverteilung
Voraussetzungen Programme wie Spiele, Bildschirmschoner, technische oder naturwissenschaftliche Simulatoren, künstlerische und andere Applikationen werden oftmals von Zufallszahlen gesteuert. Dabei können folgende Anforderungen auftreten:
Folgende Rahmenbedingungen können die Realisation zusätzlich erschweren:
Grundlagen In C[++,#] gibt es die Standardlibrary-Funktion rand(), die einen Wert zwischen 0 und RAND_MAX (0x7FFF=32767) – also 32768 verschiedene Werte liefert. (Compiler anderer Programmiersprachen sind zumeist in C++ geschrieben, daher kann dort analog vorgegangen werden.) Daraus kann folgendermaßen ein pseudozufälliges Doppelwort gebildet werden: typedef unsigned long DWORD; // mapidbg.h Da rand()seine Werte immer in der gleichen Reihenfolge liefert, werden nur bestimmte Belegungen des Doppelwortes erzeugt. Soll bestmögliche Verteilung aller Bits von Rnd::DWord()erreicht werden, sollte man unterschiedliche rand()'s verwenden: return (RMAX*RMAX*(DWORD)myrand1()+RMAX*myrand2()+myrand3()); Will man also ein Ereignis mit 17,3%iger Wahrscheinlichkeit auftreten lassen, genügt folgendes Konstrukt mit zumeist ausreichender Genauigkeit: if((Rnd::DWord()%/*modulo*/1000)<173) { /*……*/ } Sollte tatsächlich allerhöchste Präzision erforderlich sein, darf man von Rnd::DWord() nur einen Bereich auswerten, der durch den Modulokoeffizienten teilbar ist:
DWORD x; do { x=Rnd::DWord(); } while(x>=2147483000); Der eigene Generator Wer – aus welchen Gründen auch immer (z.B. wegen Reproduzierbarkeit und Steuerbarkeit) – sich einen eigenen konstanten Zufallszahlenerzeuger programmieren will, kann das folgendermaßen durchführen: static DWORD NextDW(DWORD&prev) Der Multiplikator und der Summenbildner können dabei nach eigenem Gutdünken ausgewählt werden – der resultierende Generator muss aber unbedingt getestet werden! static int my_rand(DWORD&prev) // prev ... Speicher mit altem Wert (siehe: Bjarne Stroustrup, The C++ Programming Language, Third Edition, page 685f) Die Modifikationsfunktion f(x) Will man nun nichtkonstante Wahrscheinlichkeit erreichen, erzeugt man folgendermaßen aus dem Wertebereich 0<=r<=RAND_MAX einen Wertebereich 0.0<=x<1.0: double x=((double)r)/((double)(RAND_MAX+1)); Daraus bildet man den Eingangswertebereich zu einer Funktion f(x)
und vollzieht die Transformation in den gewünschten Wertebereich: // MAX_CALC_VALS ... oberster zulässiger Wert des Ausgangsdoppelwortes Je nach Ausgestaltung von y werden jetzt z.B. kleine Werte von y häufig, große Werte von y aber selten vorkommen. Häufige Werte treten auf, wo f(x) flach ist (dy/dx«), seltene Werte an steilen Bereichen. (dy/dx»)
Auswahl der Modifikationsfunktion f(x) mit rižArtë Zur Unterstützung bei der Auswahl einer geeigneten Modifikationsfunktion wurde in dem Programm rižArtë ein eigenes Tool geschaffen. rižArtë ist Freeware und kann von der Eingangsseite dieser MJL-Homepage (links) downgeloaded werden.
Im nun erschienenen Werkzeugselektor wählen sie den Eintrag Randomizer Algorithms Analysis.
Nun erscheint ein Window, in dem Sie verschiedene Generatorenalgorithmen simulieren und testen können.
Im oberen Teil des Windows können Sie definieren, ob Sie den C-Standard- oder einen selbstdefinierten Generator verwenden wollen. Im Feld # %-Grid stellen Sie ein, auf wie viele unterschiedliche Werte die Ergebnisse projiziert werden. Mit dem Button Test wird eine Simulation gestartet. # of Generations bestimmt die Anzahl von Simulationsdurchläufen.
Im Feld Formula f(x) wird die nun eingestellte Modifikationsfunktion angezeigt. Die Funktionen enthalten alle einen konstanten Parameter c, der den Kurvenverlauf modifiziert. Normalerweise kann sich c im Bereich zwischen 0.00001 und 10000.0 bewegen. Bei Funktionen mit eingeschränktem Wertebereich für c befindet sich dessen Einschränkungsdefinition in eckiger Klammer am Ende der Formel. Das farbige Ergebnisfeld zeigt in Blau die Minima und Maxima aller Werte, die in der Darstellung auf diese Pixelbreite projizieren. Die roten Punkte sind die jeweiligen pixelbreiten Durchschnittswerte. In Gelb werden die Prozentzahlen entsprechend dem eingestellten Grid angezeigt. Im grünen Rand werden oben die Gesetzt-Häufigkeiten für einzelne Bits (vor der Modifikationsfunktion – für das Testen von my_rand()) und links das jeweilige Minimum, Maximum und der Durchschnitt über alle Werte angezeigt. Nach dem Exekutieren eines einzelnen Testdurchlaufs erscheint die Parametrierung und das Ergebnis folgendermaßen:
Während diese Anzeige aktiv ist, befinden sich die Ergebnisse als Text am Clipboard und können in einen beliebigen Texteditor eingefügt werden.
Besonderheiten einzelner Funktionen Die erste Formel liefert eine der Gauß'schen Normalverteilung ähnelnde Wahrscheinlichkeitskurve mit einer unsymmetrischen Glocke größter Häufigkeit. (Für die Erzeugung einer tatsächlichen Normalverteilung siehe http://de.wikipedia.org/wiki/Normalverteilung)
Sourcecode Rückprojektion auf den DWORD-Wertebereich. // MAX_CALC_VALS ... oberster zulässiger Wert des Ausgangsdoppelwortes [0x7FFF] Modifikationsfunktionen (in der gleichen Reihenfolge wie im Selektor):
// par_m_cst ... Funktionsparametrierungskonstante Bei Auswahl einer der obigen Funktionen können aus Gründen der Laufzeitersparnis Ausdrücke wie Falls Sie eigene Modifikationsfunktionen in das Testtool eingebracht haben wollen, wenden Sie sich bitte an rizarte@yahoo.de.
© by MJL Technische Software GmbH
|