Moin,
Es ist nur eine sehr kleine Funktion, aber ab und zu taucht die Frage wieder auf: Wie kann man mit der BuildIn Random-Funktion eine halbwegs anständige Normalverteilung zustandebringen ?
Der Trick ist, einfach mehrere (wir nehmen hier eine Gleichverteilung an) BuildIn-Randoms zu addieren und mit einem Korrekturfaktor (damit die Standardabweichung stimmt) zu versehen. In diesem Fall werden 6 float Zufallszahlen aus dem Bereich (-1, 1) verwendet, damit ist ein Maximalabstand zum Mittelwert von 6 Sigma möglich. (eine "echte" Normalverteilung hat selbstverständlich keine Beschränkung, allerdings kommen Ereignisse außerhalb von 6 Sigma nicht besonders häufig vor).
Als kleine Info: 1x Random -> Gleichverteilt, 2x Random -> "Dreieck", 3x Random -> Normalverteilung mit "Knicken", 6x Random -> Normalverteilung mit vielen, aber weniger ausgeprägten "Knicken".
#include <Array.au3>
Local $n = 100000, $aRnd[$n] ; 100.000 Testzahlen
For $i = 0 To $n - 1 Step 1
$aRnd[$i] = RandomN(30, 20) ; Mittelwert 30, Standardabweichung 20
Next
Local $aStdAbw = StdABW($aRnd) ; Mittelwert und Standardabweichung berechnen
ConsoleWrite('Mid: ' & $aStdAbw[0] & @CRLF & 'StdABW: ' & $aStdAbw[1] & @CRLF) ; Ausgabe
_ArrayDisplay($aRnd, 'Zufallszahlen', 25) ; Erste 25 Elemente anschauen
; #FUNCTION# ====================================================================================================================
; Author ........: Mars
; Description ...: Berechnet den Mittelwert und die Standardabweichung.
; ===============================================================================================================================
Func StdABW(ByRef $aArray)
Local $n = UBound($aArray), $nMid = ArraySum($aArray)/$n, $nVar = 0
For $i = 0 To $n - 1 Step 1
$nVar += ($aArray[$i] - $nMid)^2
Next
Local $aRet = [$nMid, ($nVar / ($n - 1)) ^ 0.5]
Return $aRet
EndFunc
; #FUNCTION# ====================================================================================================================
; Author ........: Mars
; Description ...: Ermittelt einen Zufallswert anhand eines gegebenen Mittelwertes und der Standardabweichung
; ...............: Obacht! Es handelt sich um KEINE richtige Normalverteilung, sondern nur um eine Näherung!
; ===============================================================================================================================
Func RandomN($nMid, $nSigma) ; Es können nur Ereignisse im 6 Sigma Bereich auftreten.
Return $nMid + $nSigma * (Random(-1, 1) + Random(-1, 1) + Random(-1, 1) + Random(-1, 1) + Random(-1, 1) + Random(-1, 1)) / 1.414214
EndFunc
; #FUNCTION# ====================================================================================================================
; Author ........: Mars
; Description ...: Summiert alle Elemente eines Arrays
; ===============================================================================================================================
Func ArraySum($aArray)
If Not IsArray($aArray) Then Return $aArray
Local $iTmp = 0
For $i = 0 To UBound($aArray) - 1 Step 1
$iTmp += $aArray[$i]
Next
Return $iTmp
EndFunc
Alles anzeigen
Hier ist ein kleines Beispiel wie die Verteilung mit der Funktion aussehen könnte (so "glatt" ist sie nur, wenn man entsprechend viele Zufallszahlen generiert. Mittelwert = 50, Standardabweichung = 12.5)
Plot.png
Edit: In Post 3 gibt es noch eine Variante für die Erzeugung zweier Normalverteilter Zufallsvariablen, die eine echte Normalverteilung liefert.
lg
M