2009-12-04 10 views
10

główny .cppboost :: random generuje ten sam numer za każdym razem

#include  "stdafx.h" 
#include  "random_generator.h" 


     int 
main (int argc, char *argv[]) 
{ 
     cout.setf(ios::fixed); 
     base_generator_type base_generator; 
     int max = pow(10, 2); 
     distribution_type dist(1, max); 

     boost::variate_generator<base_generator_type&, 
distribution_type > uni(base_generator, dist); 
     for (int i=0; i<10; i++) { 
       //cout << random_number(2) << endl; 
       cout << uni() << endl; 
     } 

     return EXIT_SUCCESS; 

}        /* ---------- end of function main ---------- */ 

random_gemerator.h

#include  "stdafx.h" 

#include  <boost/random.hpp> 
#include  <boost/generator_iterator.hpp> 

typedef boost::mt19937 base_generator_type; 
typedef boost::lagged_fibonacci19937 fibo_generator_type; 
typedef boost::uniform_int<> distribution_type; 
typedef boost::variate_generator<fibo_generator_type&, 
distribution_type> gen_type; 

     int 
random_number (int bits) 
{ 
     fibo_generator_type fibo_generator; 
     int max = pow(10, bits); 
     distribution_type dist(1, max); 

     gen_type uni(fibo_generator, dist); 
     return uni(); 

}    /* ----- end of function random_number ----- */ 

stdafx.h

#include <iostream> 
#include <cstdlib> 
#include <cmath> 

using namespace std; 

każdym razem, gdy go uruchomić, to wszystkie generują tę samą sekwencję numerów

jak 77, 33,5, 22, ...

jak używać boost: losowo poprawnie?


to jest to. ale może mieć mały problem, jak następuje:

wydaje dźwięk

get_seed(); for (;;) {cout << generate_random() << endl; } // is ok 

to genereate taką samą liczbę losową

int get_random() {get_seed();return generate_random();} for (;;) {cout << get_random() <<endl;} // output the same random number yet 

Odpowiedz

6

Trzeba nasion swój generatora liczb losowych, więc nie robi” t za każdym razem zaczynać od tego samego miejsca.

W zależności od tego, co robisz z liczbami, możesz zastanowić się, w jaki sposób wybierasz wartość początkową. Jeśli potrzebujesz wysokiej jakości losowości (jeśli generujesz klucze kryptograficzne i chcesz, aby były dość bezpieczne), będziesz potrzebował dobrej wartości początkowej. Gdyby to był Posix, sugerowałbym/dev/random - ale wyglądasz tak, jakbyś korzystał z Windowsa, więc nie jestem pewien, jakie byłoby dobre źródło nasion.

Ale jeśli nie masz nic przeciwko przewidywalnym nasieniem (do gier, symulacji itp.), Szybkie i brudne nasiono jest bieżącym znacznikiem czasu zwróconym przez czas().

+0

Ya prawo. Jeśli materiał siewny jest taki sam, generator rozpocznie się od tej samej liczby losowej za każdym razem, – A9S6

+0

to jest to.ale może mieć mały problem, jak na przykład: wydaje się dźwięk get_seed(); for (;;) {cout << generate_random() << endl; } // jest ok to genereate ta sama liczba losowa int get_random() {get_seed(); return generate_random();} dla (;;) {cout << get_random() << endl;} // output ta sama liczba losowa, ale – mono

+0

generuje ziarno za każdym razem, gdy wywoływana jest funkcja. vs używać tego samego materiału siewnego za każdym razem, gdy jest tym samym nasieniem? dlaczego dostaję tę samą sekwencję liczb losowych w poprzedni sposób – mono

13

jeśli chcesz sekwencja liczb losowych zmieniać przy każdym uruchomieniu programu, trzeba zmienić losowych przez inicjowanie go z obecnym czasie na przykład

znajdziesz przykładowe there, fragment:

/* 
* Change seed to something else. 
* 
* Caveat: std::time(0) is not a very good truly-random seed. When 
* called in rapid succession, it could return the same values, and 
* thus the same random number sequences could ensue. If not the same 
* values are returned, the values differ only slightly in the 
* lowest bits. A linear congruential generator with a small factor 
* wrapped in a uniform_smallint (see experiment) will produce the same 
* values for the first few iterations. This is because uniform_smallint 
* takes only the highest bits of the generator, and the generator itself 
* needs a few iterations to spread the initial entropy from the lowest bits 
* to the whole state. 
*/ 
generator.seed(static_cast<unsigned int>(std::time(0))); 
+0

to jest to. ale może mieć mały problem, jak na przykład: wydaje się dźwięk get_seed(); for (;;) {cout << generate_random() << endl; } // jest ok to genereate ta sama liczba losowa int get_random() {get_seed(); return generate_random();} dla (;;) {cout << get_random() << endl;} // output ta sama liczba losowa jeszcze – mono

+8

Wolę inicjowanie PRNG na 'std :: time (NULL) + getpid()'. Zapewnia to, że pliki binarne wykonywane jeden po drugim, w krótkim odstępie czasu, mają odmiennie zainicjalizowane PRNG. – user1202136

+1

Aby dodać "bezpieczeństwo", prawidłowe podejście powinno polegać na zainicjowaniu PRNG za pomocą/dev/random (lub odpowiednika w [Windows] (https://en.wikipedia.org/wiki/Entropy_ (computing) #Windows).) – Avio

5

Jeśli używasz systemu "nix", zawsze możesz spróbować czegoś takiego;

int getSeed() 
{ 
    ifstream rand("/dev/urandom"); 
    char tmp[sizeof(int)]; 
    rand.read(tmp,sizeof(int)); 
    rand.close(); 
    int* number = reinterpret_cast<int*>(tmp); 
    return (*number); 
} 

Zgaduję wysiewu generator liczb losowych w ten sposób jest szybszy niż po prostu czytając /dev/urandom (lub /dev/random) dla wszystkich potrzebuje numer losowy.

+0

To jest właściwy pomysł. Zauważ, że w nowszych wersjach Boost przynajmniej to wszystko jest dla ciebie abstrakcyjne przez 'random_device'. Jako bonus, 'random_device' powinno być również zaimplementowane w systemie Windows. Niestety, jeśli rozumiem poprawnie, nie jest on implementowany w BSD, ponieważ BSD/dev/urandom nie jest tak naprawdę niedeterministyczny. Jeśli więc zależy Ci na interoperacyjności Linuksa i systemu Windows, to możesz użyć 'random_device', a jeśli chcesz mieć kompatybilność z Linuxem i BSD, możesz użyć jawnego odczytu z/dev/urandom. Jeśli chcesz mieć jakąś inną kombinację interoperacyjności, myślę, że jesteś sam! – Chinasaur

2

Możesz używać klasy boost::random::random_device albo tak jak jest, albo aby wysiać swój inny generator.

Można dostać jednorazową liczbę losową z niego z prostą:

 
boost::random::random_device()() 

+0

Wygląda na to, że zwraca wynik typu "unsigned int" (zastanawiałem się ... więc musiałem to sprawdzić). –

Powiązane problemy