Domanda

Il codice seguente restituisce un numero casuale ogni secondo:

int main ()
{
    srand(time(NULL)); // Seeds number generator with execution time.

    while (true)
    {
        int rawRand = rand();

        std::cout << rawRand << std::endl;

        sleep(1);
    }
}

Come potrei dimensionare questi numeri verso il basso in modo che siano sempre nella gamma di 0-100?

È stato utile?

Soluzione

Se si sta utilizzando C ++ e sono preoccupati per buona distribuzione è possibile utilizzare TR1 C ++ 11 <random>.

#include <random>

std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]

std::cout << idist(rgen) << std::endl;

Altri suggerimenti

Tutti gli esempi pubblicato finora effettivamente dare risultati mal distribuiti. Eseguire il codice, spesso e creare una statistica per vedere come i valori diventano distorta.

Un modo migliore per generare un vero uniforme distribuzione del numero casuale in qualsiasi intervallo [0, N ] è la seguente (supponendo che rand realtà segue una distribuzione uniforme, che è tutt'altro che ovvio):

unsigned result;
do {
    result = rand();
} while (result > N);

Naturalmente, questo metodo è lento, ma non produrre una buona distribuzione. Un modo un po 'più intelligente di fare questo è quello di trovare il più grande multiplo di N che è più piccolo di RAND_MAX e usando come il limite superiore. Dopo di che, si può tranquillamente prendere il result % (N + 1).

Per una spiegazione perché il metodo di modulo ingenuo è male e perché quanto sopra è meglio, vedi eccellente articolo di Julienne su usando rand .

int rawRand = rand() % 101;

See (per maggiori dettagli):

rand - C ++ Reference

Altri hanno anche sottolineato che questo non sta andando per darvi la migliore distribuzione dei numeri casuali possibili. Se questo genere di cose è importante nel codice, si dovrebbe fare:

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

Modifica

A tre anni, sto facendo una modifica. Come altri hanno detto, rand() ha una grande quantità di problemi. Ovviamente, non posso raccomandare il suo uso quando non ci sono alternative migliori per il futuro. Potete leggere tutto circa i dettagli e le raccomandazioni qui:

rand () considerati nocivi | GoingNative 2013

Si può fare

cout << rawRand % 100 << endl; // Outputs between 0 and 99

cout << rawRand % 101 << endl; // outputs between 0 and 100

Per le persone downvoting; notare un minuto dopo questo è stato originariamente pubblicato ho lasciato il commento:

http://www.cplusplus.com/reference/clibrary/cstdlib/rand "Avviso però che questa operazione modulo non genera un numero casuale veramente uniformemente distribuito nel giro (poiché nella maggior parte dei casi abbassare i numeri sono leggermente più probabile), ma è generalmente una buona approssimazione per brevi campate."

Con interi a 64 bit e utilizzando 100 numeri come output, i numeri 0-16 sono rappresentati con 1,00000000000000000455% dei numeri (una precisione rispetto alla distribuito identicamente del 1% di circa 10 -18 ), mentre i numeri 17-99 sono rappresentati con ,99999999999999999913% dei numeri. Sì, non perfettamente distribuito, ma una buona approssimazione per le piccole luci.

Si noti inoltre, da dove viene il PO chiede numeri identicamente distribuite? Per quanto ne sappiamo questi vengono utilizzati per scopi dove un piccolo deviazioni non importa (ad esempio, qualcosa di diverso da crittografia - e se stanno usando i numeri per la crittografia a questa domanda è troppo ingenuo per loro di scrivere la propria crittografia ).

Modifica - Per le persone che sono veramente preoccupati di avere una distribuzione uniforme dei numeri casuali le seguenti opere di codice. Notare che questo non è necessariamente ottimale come con 64-bit interi casuali, richiederà due chiamate di rand() volta ogni 10 ^ 18 chiamate.

unsigned N = 100; // want numbers 0-99
unsigned long randTruncation = (RAND_MAX / N) * N; 
// include every number the N times by ensuring rawRand is between 0 and randTruncation - 1 or regenerate.
unsigned long rawRand = rand();

while (rawRand >= randTruncation) {
    rawRand = rand();  
// with 64-bit int and range of 0-99 will need to generate two random numbers
// about 1 in every (2^63)/16 ~ 10^18 times (1 million million times)

// with 32-bit int and range of 0-99 will need to generate two random numbers 
// once every 46 million times.

}
cout << rawRand % N << stdl::endl;

See man 3 rand -. È necessario scala dividendo per RAND_MAX per ottenere la gamma [0, 1] dopo il quale è possibile moltiplicare per 100 per il vostro target di riferimento

Per la gamma min a max (incluso), utilizzare: int result = rand() % (max - min + 1) + min;

Per quanto tempo una risposta gradite.

il più semplice è quello di convertire usando il resto quando divisi per 101:

int value = rawRand % 101;

Un semipurist sarebbe ridimensionare utilizzando raddoppia:

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5

E un purista direbbe che Rand non produce numeri casuali.

Per le tue informazioni, la qualità dei numeri casuali è misurata prendendo una sequenza di numeri e poi calcolare la probabilità matematica che la fonte di tale sequenza è stata casuale. La semplice trucco utilizzando il resto è una scelta molto povera se siete dopo la casualità.

Alcune persone hanno inviato il seguente codice di esempio:

int rawRand = (rand() / RAND_MAX) * 100;

Questo è un modo valido di risolvere il problema, in quanto entrambi rand () e RAND_MAX sono interi. In C ++, questo provoca divisione integrale, che troncare i risultati decimale punti. Come RAND_MAX> = rand (), il risultato di tale operazione è 1 o 0, significa rawRand può essere solo 0 o 100. Un corretto senso di fare questo sarebbe il seguente:

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;

Poiché uno degli operandi è ora una doppia, divisione in virgola mobile viene utilizzato, che riporta un valore adeguato tra 0 e 1.

rawRand% 101 darebbe [0-100], compreso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top