losowanie liczb większych niż 32767

0

Czy istnieje jakaś funkcja w języku C do losowania liczb większych niż 32767? Najlepiej dochodzących do około miliona.
Jeśli nie to w jaki sposób można rozwiązać ten problem?

Zastanawiam się nad pomnożeniem liczby wylosowanej przez funkcję rand() z drugą wylosowaną liczbą z zakresu np. 1-100, ale zastanawiam się czy są inne sposoby.

0
#define RAND_MAX (Gorny zakres) 

na początku, przed bibliotekami powinno pomóc

0

Nic to nie dało.
Cały czas maksymalna liczba to 32767.

0

A nie można po prostu (losowa) * 32768 + (druga losowa)?

unsigned rand_wiekszy(){
  return rand() * (RAND_MAX+1) + rand();
}
0
  1. Co do RAND_MAX to może ono przyjmować wartość conajwyżej 32767.
  2. Z tym przemnażaniem i innymi sztuczkami to trzeba być ostrożnym, bo może się okazać, że będzie losować tylko niektóre liczby z przedziału, np.

int mul = 1000000 / 32767;
int rand = mul * rand();

będzie losować 0, 30, 60, 90, czyli liczby oddalone od siebie o krotności 30stu.

  1. Jedynym słusznym spośród tych bardziej prostych rozwiązań jest użycie operacji bitowych:

unsigned int most = rand();
unsigned int least = rand();
return (most << 16) + least;

0

raczej rand()<<15 + rand()
15

0

rand() zwraca 16 bitową wartość, int ma 32 bity, więc musimy dać rand() << 16, żeby zwolnić sobie 16 młodych bitów.

unsigned int a = 1;
cout << (a << 15);
//32768

unsigned int a = 1;
cout << (a << 16);
//65536
0

Można też napisać własny generator liczb losowych np wg:
http://pl.wikipedia.org/wiki/Mersenne_Twister

0
protechnologia.pl napisał(a)

rand() zwraca 16 bitową wartość, int ma 32 bity, więc musimy dać rand() << 16, żeby zwolnić sobie 16 młodych bitów.

 int main(){
	int i;
	unsigned int r=0;
	for(i=0;i<10000;i++)
		r |= (rand()<<16) | rand();
	printf("%x\n",r);
}

Czemu otrzymujemy 7FFF 7FFF zamiast oczekiwanego FFFF FFFF?
Bit o wadze 65536 nigdy nie będzie ustawiony!!!
Bo rand() dostarcza tylko 15 bitów

Dla rand()<<15 + rand() uzyskamy liczby 30 bitowe czyli od zera do 1073741823
Lepiej zadziała (rand()<<17) (rand()<<7) (rand())
A jeszcze lepiej zastosować jakiś generator z prawdziwego zdarzenia.

0

Trochę nad tym podumałem i potestowałem i mam takie wnioski:

  1. Okazuje się, że u mnie na Fedorze rand() zwraca wynik maksymalny 7FFFFFFFh, czyli 4 bajtowy równy 2147483647d. Ale już skumałem od czego zależy, czy zwraca 2-bajtowy, czy 4-bajtowy. Rand() zwraca wynik typu int. A na niektórych systemach int jest typu short int (wtedy maksymalny wynik ma 7FFFh=32767), a na niektórych jest typu long int (maks ma wtedy 7FFFFFFFh=2147483647d).

  2. Tak jak słusznie zauważyłeś, najstarszy bit nigdy nie jest ustawiony. Wynika to z tego, że rand() daje wynik typu dodatni signed, więc najstarszy bit jest zawsze zero.

  3. Rozwiązanie od Xitami to słuszne rozwiązanie, ale je minimalnie uogólnie:

(rand() <<17 ) (rand()<<N) (rand())
gdzie N=<2,7>

0

jeżeli już uogólniać:

(rand()<<A)^(rand()<<B)^(rand())
//gdzie A=<25,30>, B=<A-14,A-7>
0

rand() jest najczęściej bardzo słabym jednowymiarowym generatorem liczb losowych, co jest wymuszone zgodnością ze standardem POSIX. Jeżeli nawet pojedyńcze wywołanie tej funkcji można traktować jako losowe, to złożenia dwóch lub więcej wywołań nie przechodzi odpowiednich testów, ze względu na to, że używając rand() kolejna wartość jest ściśle zależna od 4 bajtowego stanu (unsigned int), więc okres tego generatora wynosi maksymalnie 2^32. Tym samym jakość liczb wygenerowanych wszystkimi powyższymi metodami nie odbiega od:
int mul = 1000000 / 32767;
int rand = mul * rand();
(przy założeniu, że RAND_MAX==32767 oraz że stan jest 2 bajtowy)
Dodatkowo te xorowanie na pewno nie polepszy właściwości wygenerowanych liczb, a może nawet je pogorszyć.
W poważnych zastosowaniach należy użyć lepszych generatorów, np. random() w C (stdlib rozszerzenie POSIX) lub szeregu generatorów z <random>(boost, c++0x). Przykładowo używając Mersenne Twister można złożyć nawet 623 pojedyńcze 32. bitowe liczby w większą, pseudolosową liczbę. Polecam lekturę drugiego tomu Knutha, pierwsza część bardzo dobrze i wyczerpująco omawia problem używania liczb pseudolosowych

1 użytkowników online, w tym zalogowanych: 0, gości: 1