2013-08-10 1 views
1

J'essaie la génération de nombres aléatoires du new library in C++11 pour une classe de dés simple. Je ne suis pas vraiment saisir ce qui en fait arrive, mais la référence montre un exemple simple:Puis-je créer et détruire à plusieurs reprises des objets générateur/distributeur aléatoires et les détruire (avec une classe «dés»)?

std::default_random_engine generator; 
std::uniform_int_distribution<int> distribution(1,6); 
int dice_roll = distribution(generator); 

J'ai lu quelque part que la façon dont vous devriez que des semences « vieux » une fois (par exemple dans la fonction principale) dans votre application idéalement. Cependant, j'aimerais une classe de dés facilement réutilisable. Serait-il acceptable d'utiliser ce bloc de code dans une méthode dice::roll() bien que plusieurs objets de dés soient instanciés et détruits plusieurs fois dans une application?

Actuellement, j'ai fait le générateur en tant que membre de la classe et les deux dernières lignes sont dans les méthodes: roll(). Il semble correct mais avant de calculer les statistiques que je pensais que je demanderais ici ...

+0

Oui, c'est bien, mais pourquoi voudriez-vous créer une nouvelle distribution à chaque fois si vous avez seulement besoin de lancer des dés de toute façon? Oh, au fait, 'default_random_engine' est généralement un' linear_congruential_engine', qui est très rapide, mais qui a une corrélation sérielle. Cela peut ou peut ne pas vous intéresser. – nijansen

Répondre

1

Pensez instancier un générateur de nombres pseudo-aléatoires (PRNG) en creusant un puits - c'est la tête, vous devez aller jusqu'à être capable d'avoir accès à l'eau. Générer des instances d'un nombre pseudo-aléatoire, c'est comme plonger dans le puits. La plupart des gens ne creuseraient pas un nouveau puits chaque fois qu'ils voudraient un verre d'eau, pourquoi invoquer le surcoût inutile de plusieurs instanciations pour obtenir des nombres pseudo-aléatoires supplémentaires? Au-delà des frais généraux inutiles, il existe un risque statistique. Les implémentations sous-jacentes des PRNG sont des fonctions déterministes qui mettent à jour certains états maintenus en interne pour générer la valeur suivante. Les fonctions sont très soigneusement conçues pour donner une séquence de valeurs indépendantes (mais pas indépendantes!). Cependant, si l'état de deux ou plusieurs PRNG est initialisé de manière identique via l'ensemencement, ils produiront exactement les mêmes séquences. Si le semis est basé sur l'horloge (un défaut commun), les PRNG initialisés dans la même case de l'horloge produiront des résultats identiques. Si vos résultats statistiques ont l'indépendance comme une exigence, alors vous êtes arrosé. À moins que vous ne sachiez vraiment ce que vous faites et que vous essayez d'utiliser des stratégies d'induction de corrélation pour variance reduction, la meilleure pratique consiste à utiliser une seule instanciation d'un PRNG et à y revenir pour obtenir des valeurs supplémentaires.

+0

Donc, la solution serait d'initialiser le 'std :: default_random_engine generator' en tant que membre statique de la classe? Ou devrait-il être mis en dehors de la classe? – kluka

+1

Soit fonctionnerait bien. Quelle approche correspond le mieux à vos besoins architecturaux, ou est-elle "plus propre"? J'ai tendance à aimer les dépendances encapsulantes, mais votre kilométrage peut varier. – pjs

+1

Lors de l'amorçage: Le standard C++ spécifie précisément comment chaque URNG doit être ensemencé par défaut (sauf si le client spécifie le contraire), et ce n'est pas une horloge. C'est par une constante spécifiée par standard. C'est à dire. Si vous construisez par défaut un URNG défini par std, non seulement vous obtiendrez exactement la même séquence à chaque fois, mais même si vous portez sur une autre plateforme avec une autre implémentation, vous obtiendrez toujours exactement la même séquence à chaque fois. –

Questions connexes