Genera numeri casuali usando la libreria casuale C ++ 11

Come suggerisce il titolo, sto cercando di capire un modo per generare numeri casuali usando la nuova libreria C ++ 11. L’ho provato con questo codice:

 std::default_random_engine generator; std::uniform_real_distribution uniform_distance(1, 10.001); 

Il problema con il codice che ho è che ogni volta che lo compilo e lo eseguo, genera sempre gli stessi numeri. Quindi la mia domanda è quali altre funzioni nella libreria casuale possono ottenere ciò mentre sono veramente casuali?

Per il mio caso d’uso particolare, stavo cercando di ottenere un valore compreso nell’intervallo [1, 10]

Stephan T. Lavavej (stl) di Microsoft ha tenuto una conferenza su Going Native su come utilizzare le nuove funzioni casuali di C ++ 11 e perché non utilizzare rand() . In esso, ha incluso una diapositiva che fondamentalmente risolve la tua domanda. Ho copiato il codice da quella diapositiva di seguito.

Puoi vedere il suo discorso completo qui: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

 #include  #include  int main() { std::random_device rd; std::mt19937 mt(rd()); std::uniform_real_distribution dist(1.0, 10.0); for (int i=0; i<16; ++i) std::cout << dist(mt) << "\n"; } 

Usiamo random_device una volta per seminare il generatore di numeri casuali chiamato mt . random_device() è più lento di mt19937 , ma non ha bisogno di essere seminato perché richiede dati casuali dal tuo sistema operativo (che verrà utilizzato da varie posizioni, come ad esempio RdRand ).


Guardando questa domanda / risposta , sembra che uniform_real_distribution restituisca un numero nell'intervallo [a, b) , in cui si desidera [a, b] . Per fare ciò, la nostra uniform_real_distibution dovrebbe in realtà apparire come:

 std::uniform_real_distribution dist(1, std::nextafter(10, DBL_MAX)); 

La mia libreria “casuale” fornisce un wrapper molto conveniente attorno alle classi casuali di C ++ 11. Puoi fare quasi tutto con un semplice metodo ‘ottieni’.

Esempi:

  1. Numero casuale in un intervallo

     auto val = Random::get(-10, 10); // Integer auto val = Random::get(10.f, -10.f); // Float point 
  2. Casuale booleano

     auto val = Random::get( ) // 50% to generate true auto val = Random::get( 0.7 ) // 70% to generate true 
  3. Valore casuale da una lista std :: initilizer

     auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or... 
  4. Iteratore casuale dall’intervallo iteratore o tutto il contenitore

     auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator auto it = Random::get( vec ); // return random iterator 

E ancora più cose! Dai un’occhiata alla pagina github:

https://github.com/effolkronium/random

Ecco qualcosa che ho appena scritto seguendo queste linee ::

 #include  #include  #include  using namespace std; //============================================================== // RANDOM BACKOFF TIME //============================================================== class backoff_time_t { public: random_device rd; mt19937 mt; uniform_real_distribution dist; backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {} double rand() { return dist(mt); } }; thread_local backoff_time_t backoff_time; int main(int argc, char** argv) { double x1 = backoff_time.rand(); double x2 = backoff_time.rand(); double x3 = backoff_time.rand(); double x4 = backoff_time.rand(); return 0; } 

~

Hai due situazioni comuni. Il primo è che vuoi numeri casuali e non sei troppo preoccupato per la qualità o la velocità di esecuzione. In tal caso, utilizzare la seguente macro

 #define uniform() (rand()/(RAND_MAX + 1.0)) 

che ti dà p nell’intervallo da 0 a 1 – epsilon (a meno che RAND_MAX sia più grande della precisione di un doppio, ma ti preoccupi di questo quando ti ci si avvicina).

int x = (int) (uniforms () * N);

Ora fornisce un numero intero casuale da 0 a N -1.

Se hai bisogno di altre distribuzioni, devi trasformare p. O a volte è più facile chiamare uniforms () più volte.

Se si desidera un comportamento ripetibile, effettuare il seed con una costante, altrimenti effettuare il seed con una chiamata a time ().

Ora, se sei preoccupato della qualità o delle prestazioni di esecuzione, riscrivi uniforms (). Ma altrimenti non toccare il codice. Mantenere sempre l’uniforms () su 0-1 meno epsilon. Ora puoi avvolgere la libreria di numeri casuali C ++ per creare una migliore uniformità (), ma questa è una sorta di opzione di medio livello. Se sei preoccupato delle caratteristiche del RNG, allora vale anche la pena di investire un po ‘di tempo per capire come funzionano i metodi sottostanti, quindi fornirne uno. Quindi hai il controllo completo del codice e puoi garantire che con lo stesso seme, la sequenza sarà sempre la stessa, indipendentemente dalla piattaforma o dalla versione di C ++ a cui stai collegando.