Come posso ottenere un intervallo specifico di numeri da rand ()?

srand(time(null)); printf("%d", rand()); 

Fornisce un numero casuale ad alta gamma (0-32000), ma ho solo bisogno di circa 0-63 o 0-127, anche se non sono sicuro di come procedere. Qualsiasi aiuto?

 rand() % (max_number + 1 - minimum_number) + minimum_number 

Quindi, per 0-65:

 rand() % (65 + 1 - 0) + 0 

(ovviamente puoi lasciare lo zero, ma è lì per completezza).

Si noti che questo influenzerà leggermente la casualità, ma probabilmente non ci sarà nulla di cui preoccuparsi se non si sta facendo qualcosa di particolarmente sensibile.

controlla qui

http://c-faq.com/lib/randrange.html

Per ognuna di queste tecniche, è semplice spostare l’intervallo, se necessario; i numeri nell’intervallo [M, N] potrebbero essere generati con qualcosa di simile

 M + rand() / (RAND_MAX / (N - M + 1) + 1) 

Prendere il modulo del risultato, come hanno affermato gli altri poster, ti darà qualcosa che è quasi casuale, ma non perfettamente.

Considera questo esempio estremo, supponi di voler simulare un lancio di monete, restituendo 0 o 1. Puoi fare questo:

 isHeads = ( rand() % 2 ) == 1; 

Sembra abbastanza innocuo, giusto? Supponiamo che RAND_MAX sia solo 3. Ovviamente è molto più alto, ma il punto qui è che c’è un pregiudizio quando si usa un modulo che non divide RAND_MAX in modo uniforms. Se vuoi numeri casuali di alta qualità, avrai un problema.

Considera il mio esempio. I risultati possibili sono:

 rand() freq. rand() % 2 0 1/3 0 1 1/3 1 2 1/3 0 

Quindi, “code” avverrà il doppio delle volte come “teste”!

Il signor Atwood discute questa questione in questo articolo sull’orrore codificante

Come altri hanno notato, il semplice utilizzo di un modulo altera le probabilità per i singoli numeri in modo da preferire numeri più piccoli.

Una soluzione molto ingegnosa e valida a questo problema viene utilizzata nella class java.util.Random di Java:

 public int nextInt(int n) { if (n < = 0) throw new IllegalArgumentException("n must be positive"); if ((n & -n) == n) // ie, n is a power of 2 return (int)((n * (long)next(31)) >> 31); int bits, val; do { bits = next(31); val = bits % n; } while (bits - val + (n-1) < 0); return val; } 

Mi ci è voluto un po 'per capire perché funziona e lo lascio come un esercizio per il lettore, ma è una soluzione piuttosto concisa che garantirà che i numeri abbiano pari probabilità.

La parte importante in quel pezzo di codice è la condizione per il ciclo while , che rifiuta i numeri che rientrano nell'intervallo di numeri che altrimenti risulterebbero in una distribuzione non uniforms.

Puoi usare questo:

 int random(int min, int max){ return min + rand() / (RAND_MAX / (max - min + 1) + 1); } 

Dal:

comp.lang.c Elenco FAQ · Domanda 13.16

D: Come posso ottenere numeri casuali interi in un determinato intervallo?

A: Il modo ovvio,

 rand() % N /* POOR */ 

(che tenta di restituire numeri da 0 a N-1) è scadente, perché i bit di ordine basso di molti generatori di numeri casuali sono angosciosamente non casuali. (Vedi domanda 13.18). Un metodo migliore è qualcosa di simile

 (int)((double)rand() / ((double)RAND_MAX + 1) * N) 

Se preferisci non usare il virgola mobile, è un altro metodo

 rand() / (RAND_MAX / N + 1) 

Se hai solo bisogno di fare qualcosa con probabilità 1 / N, puoi usare

 if(rand() < (RAND_MAX+1u) / N) 

Tutti questi metodi richiedono ovviamente la conoscenza di RAND_MAX (che ANSI # definisce in) e presuppongono che N sia molto inferiore a RAND_MAX. Quando N è vicino a RAND_MAX, e se l'intervallo del generatore di numeri casuali non è un multiplo di N (cioè se (RAND_MAX + 1)% N! = 0), tutti questi metodi si interrompono: alcuni output si verificano più spesso di altri. (L'uso di virgola mobile non aiuta, il problema è che rand restituisce RAND_MAX + 1 valori distinti, che non possono essere sempre divisi equamente in n bucket.) Se questo è un problema, l'unica cosa che puoi fare è chiamare rand multiple volte, scartando alcuni valori:

 unsigned int x = (RAND_MAX + 1u) / N; unsigned int y = x * N; unsigned int r; do { r = rand(); } while(r >= y); return r / x; 

Per ognuna di queste tecniche, è semplice spostare l'intervallo, se necessario; i numeri nell'intervallo [M, N] potrebbero essere generati con qualcosa di simile

 M + rand() / (RAND_MAX / (N - M + 1) + 1) 

(Nota, a proposito, che RAND_MAX è una costante che ti dice quale sia l'intervallo fisso della funzione C rand della libreria.Non puoi impostare RAND_MAX su qualche altro valore, e non c'è modo di richiedere che i numeri di ritorno di Rand in qualche altro intervallo .)

Se si inizia con un generatore di numeri casuali che restituisce valori in virgola mobile compresi tra 0 e 1 (come l'ultima versione di PMrand a cui si fa riferimento nella domanda 13.15 o drand48 nella domanda 13.21 ), tutto ciò che si deve fare per ottenere numeri interi da Da 0 a N-1 moltiplicare l'uscita di quel generatore per N:

 (int)(drand48() * N) 

Link aggiuntivi

Riferimenti: K & R2 sec. 7.8.7 p. 168 PC Sec. 11 p. 172

Citazione da: http://c-faq.com/lib/randrange.html

 double scale = 1.0 / ((double) RAND_MAX + 1.0); int min, max; ... rval = (int)(rand() * scale * (max - min + 1) + min); 

Se non ti preoccupi eccessivamente della “casualità” dei bit di basso ordine, solo rand ()% HI_VAL.

Anche:

 (double)rand() / (double)RAND_MAX; // lazy way to get [0.0, 1.0) 

Il modo ingenuo per farlo è:

 int myRand = rand() % 66; // for 0-65 

Questa sarà probabilmente una distribuzione leggermente non uniforms (a seconda del valore massimo), ma è piuttosto vicina.

Per spiegare perché non è abbastanza uniforms, considera questo esempio molto semplificato:
Supponiamo che RAND_MAX sia 4 e desideri un numero compreso tra 0 e 2. I possibili valori che puoi ottenere sono mostrati in questa tabella:

 rand() | rand() % 3 ---------+------------ 0 | 0 1 | 1 2 | 2 3 | 0 

Vedi il problema? Se il tuo valore massimo non è un divisore pari di RAND_MAX, avrai maggiori probabilità di scegliere valori piccoli. Tuttavia, poiché RAND_MAX è in genere 32767, è probabile che il bias sia abbastanza piccolo da essere utilizzato per la maggior parte degli scopi.

Ci sono vari modi per aggirare questo problema; guarda qui per una spiegazione di come Random di Java lo gestisce.

Aggiornato per non usare un #define

 double RAND(double min, double max) { return (double)rand()/(double)RAND_MAX * (max - min) + min; } 

rand () restituirà numeri compresi tra 0 e RAND_MAX, che è almeno 32767.

Se vuoi ottenere un numero in un intervallo, puoi semplicemente usare modulo.

 int value = rand() % 66; // 0-65 

Per maggiore precisione, controlla questo articolo . Discute perché il modulo non è necessariamente buono (distribuzioni difettose, in particolare sulla fascia alta) e offre varie opzioni.

Penso che quanto segue sia parzialmente corretto. È passato un po ‘di tempo da quando ho toccato C. L’idea è di usare la divisione poiché il modulo non dà sempre risultati casuali. Ho aggiunto 1 a RAND_MAX poiché ci sono molti valori possibili che arrivano da rand compreso 0. E poiché l’intervallo è anche 0 compreso, ne ho aggiunto anche 1. Penso che la matematica sia organizzata correttamente per evitare problemi matematici interi.

 #define MK_DIVISOR(max) ((int)((unsigned int)RAND_MAX+1/(max+1))) num = rand()/MK_DIVISOR(65); 

se ti interessa la qualità dei tuoi numeri casuali non usare rand ()

usa qualche altro prng come http://en.wikipedia.org/wiki/Mersenne_twister o uno degli altri giochi di alta qualità là fuori

poi vai con il modulo.

Solo per aggiungere qualche dettaglio in più alle risposte esistenti.

L’operazione mod % eseguirà sempre una divisione completa e quindi produrrà un resto inferiore al divisore.

x% y = x – (y * floor ((x / y)))

Un esempio di una funzione di ricerca di intervallo casuale con commenti:

 uint32_t rand_range(uint32_t n, uint32_t m) { // size of range, inclusive const uint32_t length_of_range = m - n + 1; // add n so that we don't return a number below our range return (uint32_t)(rand() % length_of_range + n); } 

Un’altra proprietà interessante come sopra:

x% y = x, se x

 const uint32_t value = rand_range(1, RAND_MAX); // results in rand() % RAND_MAX + 1 // TRUE for all x = RAND_MAX, where x is the result of rand() assert(value == RAND_MAX); result of rand() 
 2 cents (ok 4 cents): n = rand() x = result l = limit n/RAND_MAX = x/l Refactor: (l/1)*(n/RAND_MAX) = (x/l)*(l/1) Gives: x = l*n/RAND_MAX int randn(int limit) { return limit*rand()/RAND_MAX; } int i; for (i = 0; i < 100; i++) { printf("%d ", randn(10)); if (!(i % 16)) printf("\n"); } > test 0 5 1 8 5 4 3 8 8 7 1 8 7 5 3 0 0 3 1 1 9 4 1 0 0 3 5 5 6 6 1 6 4 3 0 6 7 8 5 3 8 7 9 9 5 1 4 2 8 2 7 8 9 9 6 3 2 2 8 0 3 0 6 0 0 9 2 2 5 6 8 7 4 2 7 4 4 9 7 1 5 3 7 6 5 3 1 2 4 8 5 9 7 3 1 6 4 0 6 5 

Basta usare rand () per ottenere lo stesso numero casuale quando si esegue il programma più volte. vale a dire quando si esegue il programma per la prima volta produrrebbe numeri casuali x, y e z. Se si esegue nuovamente il programma, esso produrrà gli stessi numeri x, ye z osservati da me.

La soluzione che ho trovato per mantenerla unica ogni volta sta usando srand ()

Ecco il codice aggiuntivo,

 #include #include 

Per impostare l’intervallo è ansible utilizzare la formula: rand ()% (max_number + 1 – minimum_number) + minimum_number

Spero che sia d’aiuto!

O puoi usare questo:

 rand() / RAND_MAX * 65 

Ma non sono sicuro se sia la più casuale o la più veloce di tutte le risposte qui.