2009-12-04 8 views
10

principal Cppboost :: aléatoire générer le même nombre chaque fois

#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; 

chaque fois que je lance, il tous génèrent la même séquence numérique

like 77, 33,5, 22, ...

comment utiliser boost: aléatoire correctement?


c'est ça. mais peut-être un petit problème, comme ce qui suit:

il semble son

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

il genereate le même nombre aléatoire

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

Répondre

6

Vous devez semer votre générateur de nombres aléatoires de sorte qu'il n » t partir du même endroit à chaque fois. En fonction de ce que vous faites avec les nombres, vous devrez peut-être réfléchir à la façon dont vous choisissez votre valeur de départ. Si vous avez besoin d'un caractère aléatoire de haute qualité (si vous générez des clés cryptographiques et que vous voulez les sécuriser), vous aurez besoin d'une bonne valeur de départ. Si c'était Posix, je suggèrerais/dev/random - mais vous cherchez à utiliser Windows, donc je ne suis pas sûr de ce que serait une bonne source de graines.

Mais si une graine prévisible (pour les jeux, les simulations, etc.) ne vous dérange pas, une graine rapide et sale est l'horodatage actuel renvoyé par time().

+0

Ya droite. Si la graine est la même, le générateur commencera avec le même nombre aléatoire à chaque fois – A9S6

+0

c'est tout.mais peut-être avoir un petit problème, comme le suivant: il semble être get_seed(); pour (;;) {cout << generate_random() << endl; } // est correct il génère le même nombre aléatoire int get_random() {get_seed(); return generate_random();} pour (;;) {cout << get_random() << endl;} // sortie le même nombre aléatoire encore – mono

+0

génère une graine à chaque fois que la fonction est appelée. vs utiliser la même graine à chaque fois qui est la même graine? – mono

13

si vous voulez que la séquence de nombres aléatoires pour changer chaque fois que vous exécutez votre programme, vous devez changer la graine aléatoire en initialisant avec l'heure actuelle, par exemple,

vous trouverez un exemple there, extrait:

/* 
* 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

c'est tout. mais peut-être avoir un petit problème, comme le suivant: il semble être get_seed(); pour (;;) {cout << generate_random() << endl; } // est correct il génère le même nombre aléatoire int get_random() {get_seed(); return generate_random();} pour (;;) {cout << get_random() << endl;} // sortie le même nombre aléatoire encore – mono

+8

Je préfère initialiser le PRNG à 'std :: time (NULL) + getpid()'. Cela garantit que les binaires exécutés les uns après les autres, en succession rapide, ont leurs PRNG initialisés différemment. – user1202136

+1

Pour plus de "sécurité", l'approche correcte devrait être d'initialiser le PRNG en utilisant/dev/random (ou l'équivalent sous [Windows] (https://en.wikipedia.org/wiki/Entropy_ (computing) #Windows). – Avio

5

Si vous utilisez un système 'nix', vous pouvez toujours essayer quelque chose comme ça;

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); 
} 

Je devine ensemencer le générateur de nombres aléatoires de cette façon est plus rapide que la simple lecture de la /dev/urandom (ou /dev/random) pour tous vos nombres aléatoires a besoin.

+0

C'est la bonne idée. Notez que dans les versions les plus récentes de Boost au moins, tout cela est abstrait pour vous par 'random_device'. En prime, 'random_device' devrait aussi être implémenté sous Windows. Malheureusement, si je comprends bien, BSD/dev/urandom n'est pas vraiment non-déterministe. Donc, si vous voulez une interopérabilité Linux et Windows, je suppose que vous pouvez utiliser 'random_device' et si vous voulez une interopérabilité entre Linux et BSD, vous pouvez utiliser la lecture explicite de/dev/urandom. Si vous voulez une autre combinaison d'interopérabilité, je pense que vous êtes seul! – Chinasaur

2

Vous pouvez utiliser la classe boost::random::random_device telle quelle ou pour ensemencer votre autre générateur.

Vous pouvez obtenir un nombre aléatoire unique en sortir avec un simple:

 
boost::random::random_device()() 

+0

On dirait qu'il renvoie un résultat de type 'unsigned int' (je me demandais ... il fallait donc le chercher). –

Questions connexes