Wer Simulationsrechnungen durchführen will, benötigt oft normal- (oder auch anders) verteilte Zufallszahlen. Wie kommt man an die?
Eine Möglichkeit wäre, Regenwürmer zu züchten und dann deren Längen auszumessen. Gleich, wenn die Meßwerte bezüglich Mittelwert und Standardabweichung korrigiert (geeignet transformiert) sind, sollten sie eigentlich normalverteilt sein.
Einfacher ist es, sie zu berechnen.
Wir wollen Werte bestimmen, deren Häufigkeiten bzw. Auftretenswahrscheinlichkeiten der Normalverteilung f(x) = N(m,s) = N(0,1) genügen.
Dazu bestimmen wir in einem Intervall möglicher x-Werte, welches ein einfaches, sig genanntes Vielfaches der Standardabweichung 1 sein soll, einen Zufallswert. Der wird anschließend übernommen oder auch nicht, abhängig davon, ob ein zweiter Zufallswert, der zwischen 0 und 0.4, dem Maximalwert der Normalverteilung liegt, unterhalb oder oberhalb des zugehörigen f(x)-Wertes liegt.
Möglicherweise ist dies im Code leichter zu verstehen:
| Function rnd_gauss(sig As Double) As Double Dim X As Double Do X = 2 * sig * Rnd - sig Loop Until 0.4 * Rnd < 1 / Sqr(2 * 3.141592654) * Exp(-(X ^ 2) / 2) End Functionrnd_gauss = X |
Ob diese schöne Routine funktioniert, wollen wir kurz testen.
Dazu sollen furchtbar viele (= 109) normalverteilte Zufallszahlen in 100 Klassen kumuliert werden. Nach jeweils 1000 Zahlen werden die 100 Klassen dargestellt. Die Klassenbesetzungen vert(i) werden mit schwarzen Punkten dargestellt. Zum Vergleich gibt es im Hintergrund weiße, berechnete Punkte, die Sollwerte. Mit wachsender Zahl der Zufallszahlen nähern sich die schwarzen Punkte den weißen an, um sie schließlich völlig zu überdecken.
| Private Sub Command1_Click() Dim sig As Double Dim num As Integer, i As Long, vert(100) As Long Dim X As Double, Y As Double sig = 3 Picture1.Scale (-sig, 0.4)-(sig, 0) Picture1.DrawWidth = 2 i = 0 Randomize Do i = i + 1 X = rnd_gauss(sig) num = Int((X + sig) / 2 / sig * 100 + 0.5) '100 Klassen vert(num) = vert(num) + 1 If i / 1000 = i \ 1000 Then Picture1.Cls 'Bild neu malen For num = 1 To 100 X = num / 100 * 2 * sig - 3 Y = 1 / Sqr(2 * 3.141592654) * Exp(-(X ^ 2) / 2) Picture1.PSet (X, Y), QBColor(15) Picture1.PSet (X, 100 * vert(num) / i / (2 * sig)), QBColor(0) Next End If Loop Until i > 1000000000# End Sub |
So sieht das dann nach sehr kurzem Lauf dieser Routine aus (Tschuldigung übrigens für die furchtbare Farbgestaltung, ich gebe zu, die ist verbesserungsfähig!) :

In der ersten Zeile dieser Seite steht eine häßliche, den Textfluß zerstörende Klammer: "(oder auch anders)" , die darauf hinweisen soll, daß man ja andere als normalverteilte Zufallszahlen benötigen könnte. Etwa poisson-verteilte oder ähnlich hübsche Sachen.
Da wäre außer Nebensächlichem, wie dem Bereich möglicher X-Werte lediglich die Auswahlbedingung abzuändern, die hier in der Zeile steht, die mit "Loop Until ..." beginnt.
Nun also viel Erfolg beim Simulieren!