W poprzednim odcinku otrzymaliśmy całkiem przyzwoity generator liczb o rozkładzie równomiernym. Teraz uzupełnimy naszą klasę o metodę do pobierania wartości z rozkładu normalnego, zwanego też rozkładem Gaussa.
Zastosowanym algorytmem do generowania liczb losowych z rozkładu normalnego jest implementacja metody Kindermana i Monahana, zwanej ROU (ratio-of-uniforms method). Szczegóły tej metody można znaleźć w książce Wieczorkowskiego i Zielińskiego[2]
Moja implementacja w języku C++ zawarta jest w metodzie getFromNormalDistribution()
klasy RandomNumberGenerator
i wygląda następująco:
double RandomNumberGenerator::getFromNormalDistribution() {
bool ok = false ;
double limit = sqrt (2/2.718281828);
double X;
do {
double U = getFromUniformDistribution();
double V = 2 * limit * getFromUniformDistribution() - limit;
X = V / U;
if (X*X <= 2*(3-U*(4+U))) {
ok = true ;
} else if (X*X <= 2/U - 2*U) {
if (X*X <= -4* log (U)) {
ok = true ;
}
}
} while (!ok);
return X;
}
|
Jak widać używa on metody getFromUniformDistribution()
zdefiniowanej wcześniej a zwracającej nam dwie liczby z rozkładu równomiernego, jedna z przedziału (0,1) a druga z .
Dowiedz się więcej »Generator liczb pseudolosowych (cz.2) – rozkład normalny