Comme le titre l'indique, j'essaie de trouver un moyen de générer des nombres aléatoires en utilisant la nouvelle <random>
bibliothèque C ++ 11 . Je l'ai essayé avec ce code:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Le problème avec le code que j'ai est que chaque fois que je le compile et l'exécute, il génère toujours les mêmes nombres. Ma question est donc de savoir quelles autres fonctions de la bibliothèque aléatoire peuvent accomplir cela tout en étant vraiment aléatoires?
Pour mon cas d'utilisation particulier, j'essayais d'obtenir une valeur dans la plage [1, 10]
std::mt19937
comme moteur à moins que vous n'ayez une bonne raison de ne pas le faire. Et la distribution est un intervalle fermé aux deux extrémités.std::uniform_int_distribution
, qui est fermé aux deux extrémités.Réponses:
Stephan T. Lavavej (stl) de Microsoft a fait une conférence à Going Native sur la façon d'utiliser les nouvelles fonctions aléatoires C ++ 11 et pourquoi pas les utiliser
rand()
. Il y a inclus une diapositive qui résout essentiellement votre question. J'ai copié le code de cette diapositive ci-dessous.Vous pouvez voir son exposé complet ici: http://channel9.msdn.com/Events/GoingNative/2013/rand-Consemed-Harmful
Nous utilisons
random_device
une fois pour semer le générateur de nombres aléatoires nommémt
.random_device()
est plus lent quemt19937
, mais il n'a pas besoin d'être amorcé car il demande des données aléatoires à votre système d'exploitation (qui proviendra de divers endroits, comme RdRand par exemple).En regardant cette question / réponse , il semble que
uniform_real_distribution
renvoie un nombre dans la plage[a, b)
, où vous voulez[a, b]
. Pour ce faire, notreuniform_real_distibution
devrait ressembler à:la source
default_random_engine
, selon l'amorce de c ++, c'est celui que l'implémentation a jugé le plus utiledefault_random_engine
existe.std::default_container
, espérons qu'il n'y en a pas les gens se considérant comme des programmeurs qui ne connaissent pas les différences, de nombreux langages de script ont une structure de type de carte par défaut, qui pourrait être implémentée de différentes manières que l'utilisateur ne connaît peut-être pasnextafter
appel est excessif pour la plupart des applications. Les chances d'undouble
atterrissage aléatoire exactement sur le point final sont si minuscules qu'il n'y a aucune différence pratique entre l'inclure et l'exclure.std::vector
analogie ne fonctionne pas ici carstd::vector
c'est en fait un bon défaut en raison de la mise en cache du processeur. Il surpasse mêmestd::list
pour l'insertion au milieu. C'est vrai même si vous comprenez tous les conteneurs et pouvez prendre une décision éclairée basée sur la complexité algorithmique.Ma bibliothèque 'random' fournit un wrapper très pratique autour des classes aléatoires C ++ 11. Vous pouvez faire presque toutes choses avec une simple méthode «get».
Exemples:
Nombre aléatoire dans une plage
Booléen aléatoire
Valeur aléatoire d'une std :: initilizer_list
Itérateur aléatoire de la plage d'itérateur ou de tous les conteneurs
Et encore plus de choses! Consultez la page github:
https://github.com/effolkronium/random
la source
J'ai rouge tout ce qui précède, environ 40 autres pages contenant du c ++ comme ça et j'ai regardé la vidéo de Stephan T. Lavavej "STL" et je n'étais toujours pas sûr du fonctionnement des nombres aléatoires dans la praxis, alors j'ai pris un dimanche complet pour comprendre de quoi il s'agit et comment il fonctionne et peut être utilisé.
À mon avis, STL a raison de "ne plus utiliser srand" et il l'a bien expliqué dans la vidéo 2 . Il recommande également d'utiliser:
a)
void random_device_uniform()
- pour une génération chiffrée mais plus lente (d'après mon exemple)b) les exemples avec
mt19937
- plus rapide, possibilité de créer des graines, non chiffrésJ'ai sorti tous les livres c ++ 11 revendiqués auxquels j'ai accès et j'ai découvert que des auteurs allemands comme Breymann (2015) utilisent toujours un clone de
juste avec
<random>
au lieu de<time> and <cstdlib>
#includings - alors faites attention à n'apprendre qu'à partir d'un seul livre :).Cela signifie - cela ne devrait pas être utilisé depuis C ++ 11 car:
J'ai finalement trouvé la meilleure explication parmi 20 livres dans les plus récents de Bjarne Stroustrups - et il devrait connaître son affaire - dans «A tour of C ++ 2019», «Programming Principles and Practice Using C ++ 2016» et «The C ++ Programming Language 4ème édition 2014 "et aussi quelques exemples dans" Lippmans C ++ primer cinquième édition 2012 ":
Et c'est vraiment simple car un générateur de nombres aléatoires se compose de deux parties: (1) un moteur qui produit une séquence de valeurs aléatoires ou pseudo-aléatoires. (2) une distribution qui mappe ces valeurs dans une distribution mathématique dans une plage.
Malgré l'avis du gars de Microsofts STL, Bjarne Stroustrups écrit:
L'
void die_roll()
exemple est de Bjarne Stroustrups - bonne idée de génération de moteur et de distribution avecusing
(plus de détails ici) .Pour pouvoir utiliser concrètement les générateurs de nombres aléatoires fournis par la bibliothèque standard, voici un code exécutable avec différents exemples réduits au minimum nécessaire qui, espérons-le, vous feront gagner du
<random>
temps et de l'argent:Je pense que cela ajoute tout cela et comme je l'ai dit, il m'a fallu beaucoup de lecture et de temps pour le décrire à ces exemples - si vous avez d'autres informations sur la génération de nombres, je suis heureux d'en entendre parler via pm ou dans la section des commentaires et l'ajoutera si nécessaire ou modifiera cet article. Booléen
la source
Voici quelque chose que je viens d'écrire dans ce sens:
~
la source
Voici quelques ressources que vous pouvez lire sur le générateur de nombres pseudo-aléatoires.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
Fondamentalement, les nombres aléatoires dans l'ordinateur ont besoin d'une graine (ce nombre peut être l'heure système actuelle).
Remplacer
Par
la source
Vous avez deux situations courantes. La première est que vous voulez des nombres aléatoires et que vous n'êtes pas trop préoccupé par la qualité ou la vitesse d'exécution. Dans ce cas, utilisez la macro suivante
cela vous donne p compris entre 0 et 1 - epsilon (à moins que RAND_MAX ne soit plus grand que la précision d'un double, mais vous en préoccupez lorsque vous y arrivez).
int x = (int) (uniforme () * N);
Donne maintenant un entier aléatoire sur 0 à N -1.
Si vous avez besoin d'autres distributions, vous devez transformer p. Ou parfois, il est plus facile d'appeler plusieurs fois uniform ().
Si vous voulez un comportement répétable, amorcez avec une constante, sinon amorcez avec un appel à time ().
Maintenant, si vous êtes préoccupé par la qualité ou les performances d'exécution, réécrivez uniform (). Mais sinon, ne touchez pas au code. Gardez toujours uniform () sur 0 à 1 moins epsilon. Vous pouvez maintenant envelopper la bibliothèque de nombres aléatoires C ++ pour créer un meilleur uniform (), mais c'est une sorte d'option de niveau moyen. Si les caractéristiques du RNG vous préoccupent, il vaut également la peine d'investir un peu de temps pour comprendre le fonctionnement des méthodes sous-jacentes, puis de fournir une. Vous avez donc un contrôle complet du code et vous pouvez garantir qu'avec la même graine, la séquence sera toujours exactement la même, quelle que soit la plate-forme ou la version de C ++ vers laquelle vous vous liez.
la source