Autorem poniższego opracowania jest dr Piotr A. Dybczyński z Instytutu Obserwatorium Astronomiczne UAM w Poznaniu.
Generowanie liczb pseudolosowych w języku C
- Najważniejszą funkcją, generującą liczby pseudolosowe (zwane dalej dla wygody acz nieprecyzyjnie losowymi) jest funkcja random(). Jej prototyp zawarty jest w pliku nagłówkowym stdlib.h
- Funkcja jest tam opisana jako: long random(void); co oznacza, że nie ma argumentów i zwraca (losową) liczbę całkowitą typu long (aktualnie tak samo długa jak int czyli 4 bajty).
- Zwracane liczby są z zakresu od 0 do RAND_MAX, która to stała symboliczna jest również zdefiniowana w pliku nagłówkowym stdlib.h i wynosi obecnie 2147483647 .
- Drugą ważną funkcją jest srandom(). Jej prototyp też zawarty jest w pliku nagłówkowym stdlib.h
- Funkcja jest tam opisana tak: void srandom(unsigned int seed);, co oznacza, że nie zwraca żadnej wartości i oczekuje argumentu w postaci liczby całkowitej typu unsigned int.
- Argument funkcji srandom(), zwany czasami zarodkiem, zmienia sekwencję występowania liczb losowych w kolejnych wywołaniach generatora liczb losowych random().
- Jeżeli w programie nie użyjemy funkcji srandom() lub wpiszemy jako jej argument jakąś stałą całkowitą, to każde uruchomienie programu będzie korzystało z tej samej sekwencji liczb losowych. Aby tego uniknąć często stosuje się wprowadzanie przez użytkownika jakiejś liczby jako zarodka lub lepiej, samemu wstawia się tam wartość przypadkową.
- Często stosowaną w tym celu techniką jest uzależnienie zarodka od momentu uruchomienia programu. Np. instrukcja srandom((unsigned int)time(&czas)); najpierw wywołuje funkcję time(), podająca liczbę sekund od pewnej ustalonej epoki do chwili jej wywołania, potem następuje zamiana tej wartości na liczbę typu unsigned int i użycie jej jako zarodka (Funkcja time() jednocześnie zwraca czas i pakuje go pod adres podany jako argument).
- Użycie funkcji time() wymaga włączenia do kodu źródłowego pliku nagłówkowego time.h, w którym zdefiniowany jest też typ time_t.
- Więcej informacji: man 3 random, man 3 srandom, man 3 time.
- UWAGA: w bibliotece standardowej języka C są obecne również starsze funkcje rand() i srand(), które były w standardzie ANSI. Aktualnie (grudzień 2023) są to wywołania identycznego kodu co random() i srandom() i dają dokładnie te same wyniki. Różnica jest taka, że rand() zwraca wartość int a random long int, ale to tylko różnica typu, random() daje nadal liczby pseudolosowe nie większe od RAND_MAX. Można zatem używać zamiennie jednej pary funkcji lub drugiej.
Poniżej mamy przykład programu, który po skompilowaniu i uruchomieniu wypisze 10 losowych liczb całkowitych, aktualną wartość stałej RAND_MAX oraz dziesięć losowych liczb z przedziału <0,1).
/*****************************************************************
*** Przykładowy program używający liczb losowych (z zajęć) ***
******************************************************************
*** Piotr A. Dybczyński, 19-01-2023 ***
*****************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void)
{
int i;
time_t czas;
srandom( (unsigned int)time(&czas) );
for(i=0;i<10;++i)
printf("%2d %12d\n", i,random() );
printf("\nMaksymalna: %d\n\n",RAND_MAX);
for(i=0;i<10;++i)
printf("%2d %22.15f\n",i,random()/(1.0+RAND_MAX) );
return 0;
}
A oto przykładowy wynik działania powyższego programu:
0 1186171905 1 1346901345 2 173303298 3 1946555255 4 106710051 5 2013710390 6 3288553 7 549045313 8 1301775356 9 97168418 Maksymalna: 2147483647 0 0.646137747447938 1 0.020310801919550 2 0.856692060828209 3 0.225084894802421 4 0.695057923439890 5 0.634246221277863 6 0.745298271067441 7 0.066366050858051 8 0.117554211523384 9 0.663401506375521
Zadania do wykonania:
- Napisać symulator rzutu symetryczną kostką dwunastościenną i dwudziestościenną.
- Sprawdzić, ile losowań potrzeba by uzyskać pole koła metodą Monte Carlo z dokładnością 5 cyfr znaczących.
Programowe generatory liczb pseudolosowych mają bardzo bogatą literaturę. Zainteresowanym mogę polecić np. artykuł prof. Zbigniewa Kotulskiego z czasopisma Matematyka Stosowana.