Dlaczego C++ rand () wydaje się generować tylko liczby tego samego rzędu wielkości?

W małej aplikacji napisanej w C / C++ mam problem z funkcją rand i może zalążkiem:

Chcę wytworzyć ciąg liczb losowych różnych rzędów, tzn. o różnych wartościach logarytmu (baza 2). Ale wydaje się, że wszystkie produkowane liczby są tego samego rzędu, wahają się tylko między 2^25 A 2^30.

Czy to dlatego, że {[1] } jest zaszeregowany z czasem uniksowym, który jest teraz stosunkowo dużą liczbą? O czym zapomniałem ? Sieję rand() tylko raz na początku main().

 146
Author: templatetypedef, 2013-06-20

9 answers

Istnieją tylko 3% liczb między 1 A 230 które nie są pomiędzy 225 oraz 230. Więc to brzmi całkiem normalnie:)

Ponieważ 225 / 230 = 2-5 = 1/32 = 0.03125 = 3.125%

 476
Author: C4stor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-24 07:44:25

Jaśniejszy zielony to obszar między 0 a 225; ciemniejsza zieleń to obszar pomiędzy 225 oraz 230. Kleszcze to potęgi 2.

Dystrybucja

 272
Author: Casey Chu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-21 00:57:01

Musisz być bardziej precyzyjny: chcesz różne wartości logarytmu bazy 2, ale jaki rozkład chcesz do tego? Standardowe funkcje rand () generują równomierny rozkład, będziesz musiał przekształcić to wyjście za pomocą kwantyl funkcji związanej z dystrybucją, którą chcesz.

Jeśli podasz nam rozkład, to możemy podać Ci funkcję quantile, której potrzebujesz.

 42
Author: Bathsheba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 09:29:23

Jeśli chcesz różnych rzędów wielkości, dlaczego po prostu nie spróbować pow(2, rand())? A może wybrać kolejność bezpośrednio jako rand (), jak zasugerował Harold?

 18
Author: aspiring_sarge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 14:39:38

@C4stor ma rację. Ale dla bardziej ogólnego przypadku i łatwiejszego do zrozumienia dla człowieka (baza 10): dla zakresu od 1 do 10^N, ~ 90% liczb wynosi od 10^(n-1) do 10^N, dlatego ~99% liczb od 10^(n-2) do 10^n. dodawaj tyle miejsc po przecinku, ile chcesz.

Zabawna matematyka, jeśli będziesz to robił dla n, to zobaczysz, że od 1 do 10^n, 99,9999...% = 100% liczb jest od 10^0 do 10^n z tą metodą.

Teraz o kodzie, jeśli chcesz losową liczbę o losowych rządach wielkości, od 0 do 10^n, możesz zrobić:

  1. Generowanie małej liczby losowej od 0 do n

  2. Jeśli znasz zakres, który ma n, Wygeneruj dużą liczbę losową rzędu 10^k, gdzie K > max{n}.

  3. Wytnij dłuższą liczbę losową, aby uzyskać N cyfr tej dużej liczby losowej.

 13
Author: Francisco Presencia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-21 14:58:44

Podstawowa (i poprawna) odpowiedź została już udzielona i zaakceptowana powyżej: istnieje 10 liczb między 0 a 9, 90 liczb między 10 A 99, 900 między 100 a 999, itd.

Dla wydajnego obliczeniowo sposobu uzyskania rozkładu z w przybliżeniu rozkładem logarytmicznym, chcesz przesunąć swoją losową liczbę o losową liczbę:

s = rand() & 31; // a random number between 0 and 31 inclusive, assuming RAND_MAX = 2^32-1
r = rand() >> s; // right shift
To nie jest idealne, ale jest znacznie szybsze niż komputer pow(2, rand()*scalefactor). Będzie "lumpek" w tym sensie, że rozkład będzie być jednolite dla liczb w ramach czynnika 2 (jednolite dla 128 do 255, połowa gęstości dla 256 do 1023, itd.).

Oto histogram częstotliwości liczb od 0 do 31 (w próbkach 1M):

Tutaj wpisz opis obrazka

 13
Author: Floris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-25 19:21:14

Istnieje dokładnie taka sama liczba liczb od 0 do 2^29 i 2^29 i 2^30.

Inny sposób patrzenia na problem: rozważmy binarną reprezentację generowanej liczby losowej, prawdopodobieństwo, że najwyższy bit wynosi 1, jest równe 1/2, a zatem otrzymujemy kolejność 29 W połowie przypadków. Chcesz zobaczyć liczbę, która byłaby poniżej 2^25, ale to oznacza, że 5 najwyższych bitów jest zerem, co dzieje się z niskim prawdopodobieństwem 1/32. Są szanse, że nawet jeśli uruchomisz go dla długi czas nigdy nie zobaczysz kolejności poniżej 15 w ogóle (prawdopodobieństwo jest coś jak rolling 6 6 razy z rzędu).

Teraz część twojego pytania o ziarno. Nie, ziarno nie może określić zakresu, z którego generowane są liczby, określa tylko pierwszy, początkowy element. Pomyśl o rand() jako sekwencji wszystkich możliwych liczb w przedziale (z góry określona permutacja). Ziarno określa, od czego zacząć rysowanie liczb z sekwencji. Dlatego jeśli chcesz (pseudo) losowość, używasz bieżącego czasu, aby zainicjować sekwencję: nie obchodzi cię, że pozycja, z której zaczynasz, nie jest równomiernie rozłożona, liczy się tylko to, że nigdy nie zaczynasz z tej samej pozycji.

 5
Author: Vadim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-21 00:31:47

Użycie pow(2,rand()) to da odpowiedzi w kolejności pożądanej wielkości!!

 2
Author: Shivendra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-22 17:40:31

Jeśli chcesz użyć losowych liczb z serwisu internetowego, możesz użyć do tego wget, możesz zobaczyć możesz także skorzystać z takich usług jak random.org aby generować liczby losowe, możesz je złapać za pomocą wget, a następnie odczytać liczby z pobranego pliku

wget -q https://www.random.org/integers/?num=100&min=1&max=100&col=5&base=10&format=html&rnd=new -O new.txt

Http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html

 2
Author: Namit Sinha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-24 07:45:53