Strona główna » Kursy » Kurs C++ » Liczby pseudolosowe
 

Liczby pseudolosowe

Liczby pseudolosowe

Przed przystąpieniem do implementacji losowości w programie należy sobie zdać sprawę, że wylosowane liczby będą pseudolosowe. Oznacza to, że są one generowane według określonego schematu i jeśli zainicjalizujemy funkcję losującą tą samą wartością to program zwróci wylosowane liczby w tej samej kolejności. Z tego powodu należy pamiętać, aby nie używać przedstawionego sposobu losowania liczb do napisania programu zabezpieczającego dane.

Funkcje losujące

Funkcje, które posłużą do wylosowania liczb znajdują się w bibliotece cstdlib, którą dołącza się poprzez dyrektywę include:

  1. #include <cstdlib>

Następnie przed użyciem funkcji rand() do wylosowania liczby należy pamiętać, aby zainicjalizować generator liczb pseudolosowych przy pomocy funkcji srand(). Bez tego w programie dojdzie do wyjątku, który przerwie wykonywanie programu. Najprostszy program, który wylosuje dziesięć liczby ma następującą postać:

  1. #include <iostream>
  2. #include <cstdlib>
  3. using namespace std;
  4. int main() {
  5.   srand(100);
  6.   for (int i = 0; i < 10; i++)
  7.     cout << rand() << endl;
  8.   system("pause");
  9.   return 0;
  10. }

(7.) Zainicjalizowanie funkcji generującej. W tym przypadku jest ustalona jedna, stała wartość. Takie rozwiązanie powoduje, że za każdym razem będą wylosowane te same liczby w tej samej kolejności o czym można się przekonać uruchamiając program kilka razy. Co więcej bardzo prawdopodobne, że pierwszą wylosowaną liczbą będzie 365. (8.) Powtórzenie 10 razy (9.) wypisania kolejnych liczb losowych.

Uruchamiając program można zauważyć, że wszystkie liczby wypisywane są liczbami całkowitymi większymi od zera. Według oficjalnej dokumentacji funkcja rand() zwraca wartość z zakresu [0, RAND_MAX], gdzie RAND_MAX to stała wbudowana w bibliotekę cstdlib. Gwarantowane jest, że zmienna ta ma wartość co najmniej 32767. Jednak należy zawsze używać RAND_MAX zamiast wpisywać wartość na stałe w kod programu.

Sposoby losowania

Losowanie z zakresu

Najprostszym sposobem na wylosowanie liczby całkowitej z określonego zakresu [0, n - 1] jest wykorzystanie funkcji modulo:

  1.   int n = 100;
  2.   cout << rand() % n << endl;

Przedstawiony kod zwróci wartość z zakresu [0, 99]. Warto zauważyć, że dodając określoną wartość a program zwróci liczby z zakresu od [a, a + k - 1]. Zadanie to realizuje poniższy kod:

  1.   int a = 100;
  2.   int k = 100;
  3.   cout << (rand() % k) + a << endl;

Tym razem program wypisze liczby z zakresu od [100, 199]. Odpowiednio zmieniając wartości a i k można uzyskać pseudolosowe wartości z dowolnego zakresu. Użycie zmiennych w programie jest zawsze opcjonalne.

Inne losowanie z zakresu

Do losowania liczb z określonego zakresu nie zawsze trzeba polegać na funkcji modulo. Innym sposobem jest podzielić wylosowaną wartość przez maksymalną jaką można otrzymać. W ten sposób otrzymuje się wartość z zakresu [0, 1), która pomnożona przez dowolną wartość n zwróci liczbę z zakresu [0, n). Należy jednak pamiętać, że wyliczona wartość będzie liczbą rzeczywistą i może zawierać część ułamkową. W celu jej usunięcia wystarczy rzutować typ na np. int:

  1.   int n = 100;
  2.   cout << int((rand() / RAND_MAX) * n) << endl;

Funkcja losująca z określonego przedziału miałaby postać:

  1.   int a = 100;
  2.   int k = 100;
  3.   cout << int((rand() / RAND_MAX) * k) + a << endl;

Inne dane za każdym razem

Jeśli funkcja losująca została wykorzystana w jakiejkolwiek aplikacji np. w grze komputerowej straci ona na znaczeniu jeśli po każdym uruchomieniu aplikacji zawsze będą losowane te same liczby. Oznacza to, że za każdym razem należałoby znaleźć jakąś nową wartość liczbową, która przy każdym uruchomieniu byłaby inna. Najprostszym sposobem jest skorzystanie z czasu systemowego. Do tego należy dołączyć bibliotekę ctime, a następnie funkcję srand() zainicjalizować przy pomocy time(NULL) tj. aktualnym czasem systemu:

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <ctime>
  4. using namespace std;
  5. int main() {
  6.   srand(time(NULL));
  7.   for (int i = 0; i < 10; i++)
  8.     cout << rand() << " ";
  9.   system("pause");
  10.   return 0;
  11. }

Uruchamiając kilka razy program można zauważyć, że liczby różnią się nieznacznie. Mimo to jest to sposób gwarantujący różne liczby losowe za każdym razem. Jednak warto pamiętać, że użytkownik może przestawić godzinę, aby program ponownie wylosował te same wartości.

Podsumowanie

Lekcja 14 dobiegła końca. Zajrzyj do kodu źródłowego, aby przeanalizować wypisywanie danych jeszcze raz. Następnie spróbuj wykonać zadania, aby utrwalić materiał.

Zadania

W celu przećwiczenia i zrozumienia lepiej omawianego tematu warto zapoznać się z zadaniem przedstawionym w artykule Zgadnij liczbę.

Zadanie 1

Napisz program, który wczyta od użytkownika ilu cyfrową liczbę ma wylosować program. Zadaniem programu jest wylosowanie liczby całkowitej z przedziału [0, 10n - 1].

Efekt końcowy powinien wyglądać tak: