Normalverteilte Zufallszahlen


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)
rnd_gauss = X
End Function

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!) :

Normalverteilung

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!

zum Anfang

© R. Hirte * 2003