Non sono sicuro di cosa stia succedendo (ancora!), Ma è comunque possibile inizializzarlo in base al tempo come segue senza colpire il problema (preso in prestito da here).
#include <ctime>
#include <iostream>
#include <random>
#include <chrono>
using namespace std;
unsigned seed1 = std::chrono::system_clock::now().time_since_epoch().count();
default_random_engine gen(seed1); //gen(time(NULL));
uniform_int_distribution<int> dist(10,200);
int main()
{
for(int i = 0; i < 5; i++)
cout<<dist(gen)<<endl;
return 0;
}
È inoltre possibile utilizzare il dispositivo a caso, che non è determinstic (ruba cronometraggio informazioni dai vostri colpi chiave, movimenti del mouse e altre fonti per generare numeri imprevedibili). Questo è il seme più forte che puoi scegliere, ma l'orologio del computer è il modo migliore per andare se non hai bisogno di forti garanzie perché il computer può esaurire "casualità" se lo usi spesso (ci vogliono molti tratti chiave e mouse movimenti per generare un singolo numero veramente casuale).
std::random_device rd;
default_random_engine gen(rd());
Esecuzione
cout<<time(NULL)<<endl;
cout<<std::chrono::system_clock::now().time_since_epoch().count()<<endl;
cout<<rd()<<endl;
sulla mia macchina genera
1413844318
1413844318131372773
3523898368
così la libreria chrono
sta fornendo un numero significativamente più grande e più rapidamente il numero cambia (che è in nanosecondi) rispetto alla libreria ctime
. Lo random_device
sta producendo numeri non deterministici che si trovano su tutta la mappa. Quindi sembra che i semi che producono ctime
possano essere troppo vicini tra loro in qualche modo e quindi mappare in parte allo stesso stato interno?
ho fatto un altro programma che assomiglia a questo:
#include <iostream>
#include <random>
using namespace std;
int main(){
int oldval = -1;
unsigned int oldseed = -1;
cout<<"Seed\tValue\tSeed Difference"<<endl;
for(unsigned int seed=0;seed<time(NULL);seed++){
default_random_engine gen(seed);
uniform_int_distribution<int> dist(10,200);
int val = dist(gen);
if(val!=oldval){
cout<<seed<<"\t"<<val<<"\t"<<(seed-oldseed)<<endl;
oldval = val;
oldseed = seed;
}
}
}
Come si può vedere, questa stampa semplicemente il primo valore di uscita per ogni possibile seme casuale fino all'ora corrente con il seme e il numero di semi precedenti che avevano lo stesso valore.Un estratto della potenza è simile al seguente:
Seed Value Seed Difference
0 10 1
669 11 669
1338 12 669
2007 13 669
2676 14 669
3345 15 669
4014 16 669
4683 17 669
5352 18 669
6021 19 669
6690 20 669
7359 21 669
8028 22 669
8697 23 669
9366 24 669
10035 25 669
10704 26 669
11373 27 669
12042 28 669
12711 29 669
13380 30 669
14049 31 669
Così, per ogni nuovo primo numero ci sono 669 semi che danno quel primo numero. Poiché il secondo e il terzo numero sono diversi, stiamo ancora generando stati interni unici. Penso che dovremmo capire molto di più su default_random_engine
per capire cosa è speciale su 669 (che può essere scomposto in 3 e 223).
Dato questo, è chiaro il motivo per cui le librerie chrono
e random_device
funzionano meglio: i semi che generano sono sempre più di 669 a parte. Tieni presente che anche se il primo numero è lo stesso, ciò che conta in molti programmi è la sequenza di numeri generati da distinti.
Sono in grado di replicare il problema su Ubuntu 14.04 con G ++ 4.8.2 e Intel compiler 15.0.0. Interessante ... –
Sì, l'ho provato solo con il mio compilatore Ubuntu 14.10, g ++ 4.8.2, felice di non essere pazzo. – user2386276
Aggiungi una costante come 1000000 al tempo (NULL) e vedrai un diverso primo valore. Quello che vedi è previsto per qualcosa come un LCG. – user515430