04
lip
08

Generatory liczb pseudolosowych cz.3

Przyszedł czas na kolejne generatory liczb pseudolosowych. Znowu pojawi się nieco kodu oraz ogólnego wyjaśnienia pt. “Why?” ( i odpowiedzią nie będzie “For money” ;) ).

Więc do kodu start..

Kolejnym ważnym rozkładem, po wcześniej poznanym rozkładzie równomiernym, jest rozkład wykładniczy. Jest on bardzo ważny ponieważ obrazuje wiele zjawisk zarówno w telekomunikacji jak i informatyce. Przykładem są odstępy czasu pomiędzy kolejnymi zgłoszeniami w systemie telekomunikacyjnym, czy też między nowymi zadaniami w systemie operacyjnym. Jest to tzw. poissonowski strumień zgłoszeń, dotyczy on generalnie systemów kolejkowych. Poniżej kod generatora rozkładu wykładniczego o zadanej intensywności( intensywność w rozkładzie wykładniczym jest odwrotnością wartości oczekiwanej ).

class ExpotentialGenerator : public Generator
{
public:
ExpotentialGenerator( int _seed = 1, double _intensity = 0.5 );
double NextValue();
private:
UniformGenerator* uniform;
double intensity;
};

ExpotentialGenerator::ExpotentialGenerator( int _seed, double _intensity ): intensity( _intensity )
{
uniform = new UniformGenerator( _seed );
}

double ExpotentialGenerator::NextValue()
{
return -log( uniform->NextValue() )/intensity;
}

Generator opiera się na rozkładzie równomiernym [0,1], jak zdecydowana większość generatorów. Tutaj jest własnie losowana wartość z rozkładu równomiernego, z jej odwrotności liczony jest logarytm a następnie dzielimy przez intensywność ( lub mnożymy przez wartość oczekiwaną ). Zależnie co jest wygodniej dla pisanego programu można łatwo przerobić, aby argumentem wejściowym dla konstruktora była własnie wartość oczekiwana.

Przejdziemy teraz do drugiego omawianego dziś generatora – o rozkładzie Bernoulliego. Jest to rozkład, który może obrazować rzut monetą, teoretycznie prawdopodobieństwo wylosowania orła i reszki jest takie samo. Zwykle mamy dwa możliwe zdarzenia, których suma prawdopodobieństw wynosi 1. Stosujemy właśnie ten rozkład. Oto kod:

class BernoulliGenerator : public Generator
{
public:
BernoulliGenerator( int _seed, double _probability );
double NextValue();
private:
UniformGenerator* uniform;
double probability;
};

BernoulliGenerator::BernoulliGenerator( int _seed = 1, double _probability = 0.5 ): probability( _probability )
{
uniform = new UniformGenerator( _seed );
}

double BernoulliGenerator::NextValue()
{
double val = uniform->NextValue();
//// if random value belongs to “false” range return zero

if( val <= probability )
return 0.0;
else
return 1.0;
}

Sztuczka polega na tym, że losujemy liczbę w przedziale [0,1] i przedział ten dzielimy na dwie części – zgodnie z wymaganymi prawdopodobieństwami. Wartości zwracane są oczywiście umowne i zwracamy wartość odpowiadającą danemu przedziałowi. Przyjąłem tu wartości 0.0 i 1.0 czyli graniczne całego dzielonego przedziału.

W następnej części poruszymy temat generatorów rozkładu normalnego.


0 Odpowiedzi do “Generatory liczb pseudolosowych cz.3”



  1. Nie ma jeszcze komentarzy

Dodaj komentarz




 

lipiec 2008
P W Ś C P S N
« cze   sie »
 123456
78910111213
14151617181920
21222324252627
28293031  

a

Strony