Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
Współczesne języki programowania posiadają wbudowane generatory
liczb pseudolosowych udostępniające programiście swoje funkcje
poprzez prosty interfejs. W tym rozdziale pokażemy, jak się z tych
funkcji korzysta we własnych programach. |
Ziarno generatora pseudolosowego (ang. random seed) można zainicjować w języku Pascal na dwa sposoby. W pierwszym odwołujemy się bezpośrednio do zmiennej przechowującej ziarno:
randseed := nowa wartość dla ziarna pseudolosowego;
Po takiej inicjalizacji generator pseudolosowy będzie produkował zawsze ten sam ciąg liczb pseudolosowych, co można wykorzystać do prostej, amatorskiej kryptografii (zwykłe generatory LCG nie są zalecane dla profesjonalnych systemów kryptograficznych).
Drugi sposób wykorzystuje procedurę:
randomize;
Procedura randomize inicjuje randseed wartością odczytaną z zegara systemowego. Ponieważ zegar systemowy w komputerach IBM-PC działa niezależnie od reszty sprzętu, możemy go potraktować jako źródło wartości losowych – nie wiadomo przecież, w którym momencie zostanie wywołana procedura randomize. Procedurę tę wywołujemy zwykle tylko jeden raz na samym początku programu.
Zupełnie bez sensu jest poniższa konstrukcja programowa:
…
for i := 1 to 10 do
begin
randomize;
writeln(random(100));
end;
…
Jeśli komputer działa szybko, to zegar systemowy, z którego procedura randomize pobiera czas, nie zdąży się zmienić w pętli. Zatem w każdym obiegu pętli ziarno generatora pseudolosowego będzie inicjowane tą samą wartością. W efekcie generator wyprodukuje tę samą liczbę pseudolosową – aczkolwiek zwykle różną w kolejnych uruchomieniach programu, gdyż czas zegara będzie wtedy inny. Poniżej mamy wynik działania programu.
Wynik: |
19 19 19 19 19 19 19 19 19 19 |
Poprawnie program powinien wyglądać tak:
… randomize; // inicjujemy generator pseudolosowy … for i := 1 to 10 do // generujemy liczby pseudolosowe begin writeln(random(100)); end; …
Do generacji całkowitych liczb pseudolosowych wykorzystujemy funkcję
a+random(a-b+1)
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Przykładowy program generuje 10 liczb pseudolosowych z przedziału
|
Pascal// Wewnętrzny generator pseudolosowy // Data: 17.04.2008 // (C)2020 mgr Jerzy Wałaszek //---------------------------------- program prg; var i : integer; begin randomize; for i := 1 to 10 do writeln(10+random(11)); end. |
Wynik: |
19 20 16 19 19 16 11 15 12 18 |
Liczby rzeczywiste generuje funkcja random bez parametrów. Zwraca wtedy
wartość zmiennoprzecinkową typu extended (20 cyfr
znaczących) z przedziału
Jeśli chcemy wygenerować pseudolosową liczbę rzeczywistą z przedziału
a+random*(b-a)
Jeśli chcemy wygenerować pseudolosową liczbę rzeczywistą z przedziału
a+(1-random)*(b-a)
Jeśli chcemy wygenerować pseudolosową liczbę rzeczywistą z przedziału
a+random(2147483647)/2147483646*(b-a)
Jeśli chcemy wygenerować pseudolosową liczbę rzeczywistą z przedziału
a+(1+random(2147483646))/2147483647*(b-a)
Język C++ posiada wiele różnych generatorów pseudolosowych, z których najprostszym jest generator pochodzący z języka C, który tutaj opiszemy.
Dostęp do funkcji generatora pseudolosowego uzyskujemy po dołączeniu do programu pliku nagłówkowego cstdlib. Literka c na początku nazwy pliku oznacza, iż plik zawiera definicje pochodzące z języka C. Język C, poprzednik języka C++, przez wiele lat królował wśród programistów, np. system operacyjny Windows był napisany pierwotnie w języku C. W języku tym stworzono olbrzymią bazę programów, wychowało się na nim wielu programistów (łącznie z moją skromną osobą). Następca języka C, język C++, jest do pewnego stopnia kompatybilny ze swoim poprzednikiem. Dlatego w C++ możemy korzystać z funkcji języka C. Zatem, jeśli w swoim programie chcesz korzystać z generatora pseudolosowego z języka C, umieść na jego początku dyrektywę:
#include <cstdlib>
Generator pseudolosowy jest inicjowany za pomocą funkcji:
srand(x0);
Argument x0
zostanie użyty jako ziarno generacji liczb pseudolosowych. Oby otrzymywać
w programach bardziej losowe ciągi liczb pseudolosowych, generator inicjujemy
wybraną wartością losową, np. wynikiem funkcji
#include <cstdlib> // funkcje z C #include <ctime> // funkcje czasu z C … srand(time(NULL)); …
Ponieważ czas jest zliczany niezależnie od procesów obliczeniowych komputera,
to nie wiadomo, w którym momencie program zostanie uruchomiony i wywołana będzie
funkcja
Inicjalizację generatora pseudolosowego wykonujemy tylko jeden raz, zawsze na
początku programu, przed generacją liczb pseudolosowych. Nie ma sensu
umieszczanie wywołania funkcji
Dostęp do kolejnych liczb pseudolosowych uzyskujemy za pomocą funkcji
Jeśli wystarcza nam 15 bitowy zakres liczb pseudolosowych, to do generacji liczby pseudolosowej w przedziale stosujemy prosty wzór:
a+rand()%(b-a+1)
Lepszym rozwiązaniem będzie sprowadzenie wyniku
a+(int)(((double)rand()/(double)RAND_MAX)*(b-a))
Jeśli potrzebujemy większego zakresu liczb pseudolosowych niż 15 bitów, to
możemy wykorzystać funkcję
16 bitów: |
(rand() | (rand() << 15)) & 0xFFFF |
20 bitów: |
(rand() | (rand() << 15)) & 0xFFFFF |
24 bity: |
(rand() | (rand() << 15)) & 0xFFFFFF |
32 bity: |
(rand() | (rand() << 15) | (rand() << 30)) & 0xFFFFFF |
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Program demonstruje sposób uzyskania 64-bitowych liczb pseudolosowych przy pomocy wbudowanego generatora pseudolosowego. Lepszym jednakże rozwiązaniem jest zaprojektowanie własnego generatora pseudolosowego o okresie 64-bitowym, ponieważ jakość tak otrzymanych liczb pseudolosowych nie jest najlepsza. |
// Generacja 64-bitwych liczb pseudolosowych // Data: 18.04.2008 // (C)2020 mgr Jerzy Wałaszek //------------------------------------------ #include <cstdlib> #include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> using namespace std; typedef unsigned long long ulong; int main() { ulong X; int i; srand(time(NULL)); for(i = 1; i <= 20; i++) { X = (ulong)rand()|((ulong)rand() << 15)| ((ulong)rand() << 30)|((ulong)rand() << 45)| ((ulong)rand() << 60); cout << setw(20) << X << endl; } cout << endl; return 0; } |
Wynik: |
15909354788557317506 5646388612325884585 7784116433065307603 6793609578895196532 5097235556346604900 12640517263571584278 12678029710029330624 3892314973318364887 10783580981138539261 11361218186090798356 8678502750446328685 2341839668675288386 4165020744942595238 9942264302309224210 18329511796073573700 11968297997906007137 12073339878835311061 11130308925736402900 10947078756288983245 8939441636943881298 |
Do generacji rzeczywistych liczb pseudolosowych wynik funkcji
<0, 1) |
: (double)rand()/(double)(RAND_MAX+1) |
<0, 1> |
: (double)rand()/(double)(RAND_MAX) |
(0, 1> |
: 1-(double)rand()/(double)(RAND_MAX+1) |
(0, 1) |
: (double)(1+rand())/(double)(RAND_MAX+2) |
Rzeczywistą liczbę pseudolosową z przedziału
a+liczba_pseudolosowa{0…1}*(b-a)
Na przykład chcemy wygenerować liczbę pseudolosową w przedziale od
2.5+(double)rand()/(double)(RAND_MAX)*1.5
W języku
Standardowy generator liczb
pseudolosowych języka
Generator pseudolosowy jest klasą
default_random_engine | : | wybrany generator pseudolosowy, który daje dobre wyniki w typowych, prostych zastosowaniach. |
minstd_rand | : | prosty, liniowy generator
multiplikatywny LCG: x = x * 48271 % 2147483647 |
minstd_rand0 | : | prosty, liniowy generator
multiplikatywny LCG: x = x * 16807 % 2147483647 |
mt19937 | : | generator pseudolosowy typu Mersenne Twister. Daje w wyniku liczby 32-bitowe. |
mt19937_64 | : | generator pseudolosowy typu Mersenne Twister. Daje w wyniku liczby 64-bitowe. |
ranlux24_base | generator pseudolosowy typu Ranlux o podstawie 24-bitowej. Daje w wyniku liczby 32-bitowe. | |
ranlux48_base | generator pseudolosowy typu Ranlux o podstawie 48-bitowej. Daje w wyniku liczby 64-bitowe. | |
ranlux24 | generator pseudolosowy typu Ranlux o podstawie 24-bitowej z przyspieszonym postępem. Daje w wyniku liczby 32-bitowe. | |
ranlux48 | generator pseudolosowy typu Ranlux o podstawie 48-bitowej z przyspieszonym postępem. Daje w wyniku liczby 64-bitowe. | |
knuth_b | generator pseudolosowy typu Knuth-B. Daje w wyniku liczby 32 bitowe. |
Każda klasa generatora posiada funkcje składowe:
(konstruktor) | : | tworzy obiekt danej klasy i inicjuje jego elementy składowe, tak aby był gotowy do użytku. Jako parametr dla konstruktora przekazuje się ziarno typu całkowitego bez znaku. |
min() | : | zwraca minimalną wartość generowanych liczb pseudolosowych. |
max() | : | zwraca maksymalną wartość generowanych liczb pseudolosowych. |
seed (v) | inicjuje na nową wartość wewnętrzne ziarno pseudolosowe wg wartości v. | |
operator() | generuje kolejną liczbę pseudolosową i zwraca ją jako wynik operatora nawiasy(). | |
discard() | generuje kolejną liczbę pseudolosową, lecz nie zwraca jej. |
Zobaczmy, jak to działa w praktyce. Najpierw musisz włączyć
obsługę standardu 11 języka
Poniższy program tworzy różne generatory liczb pseudolosowych i wyświetla informacje o zakresach generowanych przez nie liczb.
// Liczby pseudolosowe // (C)2020 mgr Jerzy Wałaszek //--------------------------- #include <iostream> #include <ctime> #include <random> using namespace std; int main() { setlocale(LC_ALL, ""); cout << "Zakresy bibliotecznych generatorów pseudolosowych" << endl << "-------------------------------------------------" << endl << endl; // Tworzymy klasy generatorów pseudolosowych default_random_engine dgen(time(NULL)); minstd_rand mgen(time(NULL)); minstd_rand0 m0gen(time(NULL)); mt19937 mtgen(time(NULL)); mt19937_64 mt64gen(time(NULL)); ranlux24_base rl24gen(time(NULL)); ranlux48_base rl48gen(time(NULL)); knuth_b kbgen(time(NULL)); // Wyświetlamy zakresy liczb pseudolosowych dla każdego generatora cout << "standardowy : " << dgen.min() << " … " << dgen.max() << endl; cout << "multiplikatywny LCG : " << mgen.min() << " … " << mgen.max() << endl; cout << "multiplikatywny LCG 0: " << m0gen.min() << " … " << m0gen.max() << endl; cout << "Mersenne Twister : " << mtgen.min() << " … " << mtgen.max() << endl; cout << "Mersenne Twister 64 : " << mt64gen.min() << " … " << mt64gen.max() << endl; cout << "Ranlux 24-bitowy : " << rl24gen.min() << " … " << rl24gen.max() << endl; cout << "Ranlux 48-bitowy : " << rl48gen.min() << " … " << rl48gen.max() << endl; cout << endl; return 0; } |
Wynik: |
Zakresy bibliotecznych generatorów pseudolosowych ------------------------------------------------- standardowy : 1 … 2147483646 multiplikatywny LCG : 1 … 2147483646 multiplikatywny LCG 0: 1 … 2147483646 Mersenne Twister : 0 … 4294967295 Mersenne Twister 64 : 0 … 18446744073709551615 Ranlux 24-bitowy : 0 … 16777215 Ranlux 48-bitowy : 0 … 281474976710655 |
Następny program generuje 15 liczb pseudolosowych za pomocą wybranego generatora pseudolosowego. Generator możesz zmienić na inny.
// Liczby pseudolosowe // (C)2020 mgr Jerzy Wałaszek //--------------------------- #include <iostream> #include <ctime> #include <random> #include <iomanip> using namespace std; int main() { cout << "Generacja liczb pseudolosowych generatorem Mersenne Twister" << endl << "-----------------------------------------------------------" << endl << endl; // Tworzymy generator pseudolosowy Mersenne Twister mt19937_64 mt64gen(time(NULL)); // Wyświetlamy 15 liczb pseudolosowych for(int i = 0; i < 15; i++) cout << setw(22) << mt64gen() << endl; cout << endl; return 0; } |
Wynik: |
Generacja liczb pseudolosowych generatorem Mersenne Twister ----------------------------------------------------------- 10537470712149690863 16289189653767349705 17446861035845780457 8462092411226512412 11670304320697365710 89603159830766338 11893928287530825151 4391792179446479643 5359857403735253840 939567318540422672 1708525228151313803 7177467170986783977 12812186784476095291 9706571523780530581 17589396534050711681 |
Jeśli chcesz otrzymywać liczby z zakresu
A+generator()%(B-A+1)
Istnieje jednak lepszy sposób, który wykorzystuje rozkład generowanych liczb. Rozkład określa prawdopodobieństwo pojawienia się określonej wartości w zakresie generowanych liczb. Jeśli prawdopodobieństwo każdej wartości w zakresie jest takie samo, to mamy do czynienia z rozkładem jednorodnym (ang. uniform distribution). Rozkład nazywamy dyskretnym, jeśli w podanym zakresie liczby mogą przyjmować tylko wybrane wartości (np. całkowite).
Biblioteka random udostępnia mnóstwo różnych rozkładów, których dokładne omówienie wykracza poza ramy tego artykułu.
Rozkład w bibliotece random jest klasą. Zasady użycia są następujące:
Poniższy program generuje 200 liczb pseudolosowych o rozkładzie jednorodnym.
// Liczby pseudolosowe // (C)2020 mgr Jerzy Wałaszek //--------------------------- #include <iostream> #include <ctime> #include <random> #include <iomanip> using namespace std; int main() { setlocale(LC_ALL, ""); cout << "200 liczb pseudolosowych od 1 do 999 o rozkładzie jednorodnym" << endl << "-------------------------------------------------------------" << endl << endl; // Tworzymy klasę szablonową int rozkładu jednorodnego uniform_int_distribution<int> dist(1, 999); // Tworzymy standardowy generator pseudolosowy default_random_engine gen(time(NULL)); // Wyświetlamy 200 liczb pseudolosowych int c = 0; for(int i = 0; i < 200; i++) { cout << setw(4) << dist(gen); |
Wynik: |
200 liczb pseudolosowych od 1 do 999 o rozkładzie jednorodnym ------------------------------------------------------------- 573 919 35 724 241 623 106 20 82 683 348 233 137 86 408 63 412 421 587 607 258 98 355 342 460 672 321 263 826 787 566 971 51 926 816 717 123 672 934 280 408 420 474 933 267 81 139 854 987 419 480 307 248 827 297 164 85 819 579 958 700 226 399 256 436 158 283 405 259 162 122 32 698 944 703 57 552 928 498 45 951 516 167 871 772 782 119 133 770 156 788 844 272 726 856 927 678 644 892 503 124 696 332 919 855 357 369 751 227 387 956 786 707 827 193 582 829 395 10 11 861 638 255 437 80 473 237 53 380 314 874 728 443 586 624 196 813 612 530 778 965 817 821 334 548 610 647 386 437 806 781 806 756 60 961 360 142 748 270 435 143 857 623 427 801 409 388 656 922 956 252 54 40 442 825 103 297 195 91 642 191 549 537 140 565 425 247 305 938 687 132 996 955 424 24 668 189 463 479 275 |
Biblioteka random pozwala również na generowanie rzeczywistych liczb
pseudolosowych za pomocą obiektów rozkładu. Przy obiekcie rozkładu
uniform_real_distribution parametry
// Liczby zmiennoprzecinkowe // (C)2020 mgr Jerzy Wałaszek //--------------------------- #include <iostream> #include <random> #include <ctime> #include <iomanip> using namespace std; int main() { double a, b, x; cout << setprecision(5) << fixed; cout << "Zmiennoprzecinkowe liczby pseudolosowe w przedziale <a, b)" << endl << "---------------------------------------------------------" << endl << endl << "Podaj granice:" << endl; // Odczytujemy granice przedziału liczb pseudolosowych cout << "a = ? "; cin >> a; cout << "b = ? "; cin >> b; cout << endl; // Tworzymy obiekt generatora pseudolosowego i inicjujemy go mt19937 gen(time(NULL)); // Tworzymy klasę rozkładu: // Rozkład jednorodny liczb rzeczywistych w przedziale <a, b) uniform_real_distribution <double> dist(a, b); // Generujemy 10 liczb pseudolosowych for(int i = 0; i < 10; i++) { x = dist(gen); cout << setw(12) << x << endl; }; cout << endl; return 0; } |
Wynik: |
Zmiennoprzecinkowe liczby pseudolosowe w przedziale <a, b) --------------------------------------------------------- Podaj granice: a = ? -10 b = ? 10 -1.49019 -0.70826 5.20275 3.89604 8.31401 0.76755 -7.90011 -2.96140 5.07277 -3.50012 |
Ziarno generatora pseudolosowego inicjujemy za pomocą instrukcji:
Randomize X0
Aby otrzymywać przy każdym uruchomieniu programu inne sekwencje liczb pseudolosowych, jako ziarno stosuje się wartość licznika czasu:
Randomize Timer
Inicjalizację generatora pseudolosowego wykonuje się jeden raz na samym początku programu. Zobacz na odpowiednie przykłady dla języka Pascal – w Basicu jest bardzo podobnie.
W języku Basic istnieje funkcja Rnd, która zwraca tylko
rzeczywistą wartość pseudolosową z przedziału
a+Int(Rnd*(b-a+1)) lub a+Cint(Rnd*(b-a))
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Program wyświetla 15 liczb
pseudolosowych z przedziału całkowitego |
Basic' Wbudowany generator liczb pseudolosowych ' Data: 18.04.2008 ' (C)2020 mgr Jerzy Wałaszek '----------------------------------------- Dim i As Integer Randomize Timer For i = 1 To 15 Print Int(Rnd*11)+20 Next End |
Wynik: |
26 23 30 28 26 27 20 27 25 30 25 27 26 22 25 |
W języku Basic funkcja Rnd zwraca rzeczywistą liczbę pseudolosową
z przedziału
Aby uzyskać rzeczywistą liczbę pseudolosową w przedziale
a+Rnd*(b-a)
Aby uzyskać rzeczywistą liczbę pseudolosową w przedziale (
a+(1-Rnd)*(b-a)
Aby uzyskać rzeczywistą liczbę pseudolosową w przedziale domkniętym stosujemy konstrukcję:
If Rnd > 0.5) Then x = a+Rnd*(b-a) Else x = a+(1-Rnd)*(b-a) End If
Aby uzyskać rzeczywistą liczbę pseudolosową w przedziale otwartym
Do x = a+Rnd*(b-a) Loop Until x <> a
Język Python udostępnia moduł random do generacji liczb pseudolosowych. Liczby te powstają w wewnętrznym generatorze Mersenne Twister. Aby skorzystać z funkcji modułu random, musisz go dołączyć do swojego programu:
… import random …
Wewnętrzny generator pseudolosowy jest automatycznie inicjowany przy starcie programu. Zatem przy każdym uruchomieniu otrzymamy inny ciąg liczb pseudolosowych. Uruchom kilka razy poniższy program i porównaj wyniki.
Python
(dodatek)# Liczby pseudolosowe # Data : 17.02.2024 # (C)2024 mgr Jerzy Wałaszek # --------------------------- import random for i in range(10): print("x%1d = %6.4f" % (i, random.random())) |
Wynik: |
x0 = 0.2078 x1 = 0.9407 x2 = 0.6044 x3 = 0.0972 x4 = 0.5944 x5 = 0.5142 x6 = 0.6073 x7 = 0.3462 x8 = 0.6713 x9 = 0.4202 |
/, .
Funkcja random.random( ) jest bezparametrowa i zwraca liczbę
pseudolosową rzeczywistą z przedziału lewostronnie domkniętego
Następny program ustawia ziarno generatora przed rozpoczęciem generacji liczb pseudolosowych:
Python
(dodatek)# Liczby pseudolosowe # Data : 17.02.2024 # (C)2024 mgr Jerzy Wałaszek # --------------------------- import random random.seed(10) for i in range(10): print("x%1d = %6.4f" % (i, random.random())) |
Wynik: |
x0 = 0.5714 x1 = 0.4289 x2 = 0.5781 x3 = 0.2061 x4 = 0.8133 x5 = 0.8236 x6 = 0.6535 x7 = 0.1602 x8 = 0.5207 x9 = 0.3278 |
Funkcja random.seed( ) pozwala ustawiać w różny sposób ziarno generatora. Jeśli ziarno nie jest zdefiniowane, to generator zostanie zainicjowany bieżącym czasem systemu.
Parametr n funkcji random.seed(n) jest liczbą całkowitą (wartości innych typów muszą być zamienione na liczbę całkowitą). Jeśli parametr n zostanie pominięty, to jako ziarno generatora pseudolosowego zostanie użyty czas systemowy. Uruchom powyższy program kilkakrotnie i wyciągnij wnioski.
Funkcja random.random( )
zwraca liczbę pseudolosową z przedziału
Python
(dodatek)# Liczby pseudolosowe # Data : 17.02.2024 # (C)2024 mgr Jerzy Wałaszek # --------------------------- import random a = float(input("a = ")) b = float(input("b = ")) for i in range(10): print("x%1d = %9.4f" % (i, random.uniform(a, b))) |
Wynik: |
a = -999 b = 999 x0 = -769.4328 x1 = -731.6576 x2 = 977.0122 x3 = 328.0549 x4 = -842.0332 x5 = -169.9523 x6 = -895.1615 x7 = -748.6257 x8 = 670.3304 x9 = -723.4715 |
Do generacji liczb całkowitych używamy funkcję:
random.randrange(start, stop, przyrost)
start : dolna granica
stop : górna granica
przyrost : określa, co ile zmieniają się wartości w przedziale
Poniższy program generuje liczby pseudolosowe z przedziału
Python
(dodatek)# Liczby pseudolosowe # Data : 17.02.2024 # (C)2024 mgr Jerzy Wałaszek # --------------------------- import random for i in range(10): print(random.randrange(1, 7), end=" ") print() |
Wynik: |
2 3 3 4 6 6 6 1 4 3 |
Moduł random zawiera więcej funkcji. Ich opis znajdziesz w instrukcji języka Python.
random |
: | moduł z funkcjami generacji liczb pseudolosowych. |
random.seed(n)
|
: | ziarno pseudolosowe generatora Mersenne Twister. Jeśli parametr n zostanie pominięty, to ziarno będzie ustawione wartością czasu systemowego. |
random.random() |
: | rzeczywista liczba pseudolosowa z przedziału |
random.uniform(a, b) |
: | rzeczywista liczba pseudolosowa z przedziału |
random.randrange(a, b, k) |
: | całkowita liczba pseudolosowa z przedziału |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.