[C++]funkcja rand() a przedział losowania

Hmm nie mogę zrozumieć przedziału tej funkcji.

rand()%5

da nam losowe liczby od 0 do 4

rand()%5+1

da nam losowe liczby od 0 do 5 więc dlaczego w tym kodzie

int a;

	string array[12] = {"A","I","M","R","T","X","-"," ","?","!","#","*"};

    system("color 02");

		Sleep(85);

	for(int i=0; i<40; i++)

	{

		a = rand()%12;

		cout << array[a] << " ";

   }

występuje błąd przy kompilacji jeśli chcę przedziału 0,12 czyli

rand()%12+1

?

Oczywiście wszystko działa gdy dam samo 12

Zastanów się co napisałeś (na czerwono zaznaczyłem to nad czym powinieneś się zastanowić):

(btw jeśli tablica ma 12 elementów to na pewno chcesz przedział od 0 do 12, a nie od 0 do 11?

Po pierwsze

rand() % N

da wartości z przedziału 0 … N - 1

Jeśli dodasz do tego wyrażenia stałą C to dostaniesz przedział C … C + N - 1

Co jest logiczne, bo jeśli dodasz nieujemną wartość np. do 1 to nie dostaniesz w żaden sposób zera.

Jeśli chcesz mieć indeksy 12 elementowej tablicy to poprawne indeksy są z zakresu 0 … 11, a rand() % 12 + 1 może dać 12 i wyjść poza zakres.

Na prawdę zastanowił bym się nad wpisaniem liczby 13 zamiast 12.

Dalej jakoś nie mogę tego zrozumieć jeśli chcę losować liczby z przedziału 0,12 to daje

rand()%12+1

ale jeśli z tablicy która posiada 12 znaków chcę wylosować jeden z 12 muszę podać

rand()12

Jakim cudem otrzymam też wartość 12 ?

Wszystko zostało napisane powyżej. Mylisz się. Nie wiesz jak działa operator modulo? Jakaś wartość nieujemna modulo N daje wartości z przedziału 0 … N-1. Jeśli dodasz do takiej wartości jakąś stałą C to przedział zmieni się na 0 + C … N - 1 + C.

Ponadto, jeśli masz tablicę M-elementową, to poprawne indeksy są z zakresu 0 … M - 1.

Co jeszcze jest niejasne?

rand()% 0+1 ... (10-1)+1 = rand()10+1

czy to co zapisałem jest poprawne ?

Nie jasne jest dla mnie dlaczego przy tablicach nie może być zakres 13 jakim cudem może wykroczyć po za zakres skoro zawsze jest 0+1 … (max-1) +1 to daje zawsze max.

Witam,

  1. Zastanów się co chcesz uzyskać?

  2. Pomyśl i przeanalizuj opis kolegów odnośnie działania operatora modulo (%).

  3. Przemyśl operacje na tablicach i ich indeksowanie.

  4. Zastanów się z jakiego zakresu potrzebne są Ci wartości?

Po przerobieniu ze zrozumieniem tych kroków powinieneś bez problemu ogarnąć wiedzę i zdobyć umiejętności na rozwiązanie swojego problemu. Takie strzelanie na oślep jest mniej skuteczne niż zrozumienie.

Powodzenia

Teraz już rozumiem gdy wpiszę

rand()%12

otrzymam właśnie te znaki które chcę będzie ich 12 bo 1 jest oznaczana jako 0 a gdy wezmę zakres

rand()%12+1

to otrzymam znaki od 1 do 13 a 13 wykracza za moją tablicę. A przy losowaniu liczb korzystam z zakresu 12+1 bo nie potrzebne mi 0. Dzięki za pomoc

Gynvael ma ciekawe prezentacje na ten temat:

Generalnie: używanie modulo do określenia przedziału ma pewne wady (rozkład wartości nie musi być normalny).

Gratuluję zrozumienia i rozwiązania problemu.

Dodam jeszcze, że ogólnie wybieranie przedziałów można zapisać w następujący (ogólny sposób) dla liczb całkowitych.

Powiedzmy, że chcemy przedział np. <3;11> (drugi kraniec wchodzi do przedziału) to:

  1. obliczamy szerokość przedziału s = b-a+1 (czyli w tym przykładzie s = 11-3+1 = 9), bo 3,4,5,6,7,8,9,10,11 w sumie 9 liczb.

  2. oczekiwana minimalna wartość to a (w tym przykładzie 3) więc cały wynik losowania modulo trzeba przesunąć o tą wartość.

  3. jaka powinna być wartość modulo? Ano dokładnie taka ile wynosi szerokość przedziału obliczona w kroku 1, czyli s (dla tego przykładu s=9). Modulo zwróci nam wartości od 0 do s-1 (czyli dla tego przykładu od 0 do 8 ). Po przesunięciu o wartość minimalną a (czyli 3 dla tego przykładu) otrzymamy dokładnie to o co nam chodziło:

(dla tego przykładu <3; 9-1+3> => <3;11>)

Całkowity zapis wyglądałby tak:

rand() % s + a

czyli dla tego przykładu:

rand()%9 + 3

Sądzę, że jest to jedno z najjaśniejszych wyjaśnień (teoria + przykład) i że pomoże to innym adeptom losowania wartości.

Powodzenia.

Dzień dobry. Czy dobrze rozumiem z waszego wyjaśnienia, że jeżeli np. chcemy otrzymać losową liczbę z przedziału <122; 367> to trzeba wpisać funkcję rand tak:
rand() % 246 + 122;
ponieważ
rand() % s + a // s = 367 - 122 + 1 = 246; a = 122
Mam nadzieję, że dobrze rozumiem. Dziękuję wcześniej za odpowiedź! :slight_smile: