Przejdź do treści

C++

Generator liczb pseudolosowych (cz.3) – rozkład Cauchy’ego

  • przez

Witajcie, zgodnie z obietnicą, w tym odcinku generujemy liczby losowe z rozkładu Cauchy’ego.

Jak w poprzednim odcinku, użyjemy generatora rozkładu równomiernego. Kod metody getFromCauchyDistribution() wygląda następująco:

double RandomNumberGenerator::getFromCauchyDistribution() {

    // generuj X o rozkładzie równomiernym U(-1,1)
    double X = getFromUniformDistribution() * 2 - 1;

    // generuj X o rozkładzie równomiernym U(0,1)
    double U = getFromUniformDistribution();

    if ((U + 0.27324) * (1 + X * X) > 1.27324) {
        X = getFromUniformDistribution() * 2 - 1;
    }

    // uzupelnienie rozkładu o "ramiona"
    if (getFromUniformDistribution() > 0.5) {
        return X;
    } else {
        if (X != 0) {
            return (1 / X);
        } else {
            return MAXDOUBLE;
        }
    }
}

Dowiedz się więcej »Generator liczb pseudolosowych (cz.3) – rozkład Cauchy’ego

Generator liczb pseudolosowych (cz.2) – rozkład normalny

  • przez

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 {
        // generuj U o rozkładzie równomiernym U(0,1)
        double U = getFromUniformDistribution();

        // generuj V o rozkładzie równomiernym
        // U(-sqrt(2/e),sqrt(2/e))

        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 (-sqrt(2/e), sqrt(2/e)).

Dowiedz się więcej »Generator liczb pseudolosowych (cz.2) – rozkład normalny

Generator liczb pseudolosowych (cz.1)

  • przez

Chcemy uzyskać generator o rozkładzie normalnym oraz Cauchy’ego… Na początek jednak jako podstawa potrzebny nam będzie generator o rozkładzie równomiernym.

Zdefiniujmy sobie klasę RandomNumberGenerator:

class RandomNumberGenerator {

    private:

        double a,b,c;
        static RandomNumberGenerator* instance;

    protected:

        RandomNumberGenerator();

    public:

        static RandomNumberGenerator* getInstance();
        void init();

        double getFromUniformDistribution();
        double getFromNormalDistribution();
        double getFromCauchyDistribution();
};

Klasa jak widać będzie miała trzy metody do pobierania losowych wartości z różnych rozkładów. Zaimplementujmy pierwszy rozkład, używając do tego celu tzw. ogólnego generatora liniowego. Generator ten realizuje schemat liniowy:

Dowiedz się więcej »Generator liczb pseudolosowych (cz.1)