C ++ Nombre aléatoire entre 0 et 1

C ++ Nombre aléatoire entre 0 et 1
Un nombre aléatoire est généré dans une plage, d'un nombre minimum à un nombre maximum. Supposons que ces nombres minimum et maximum sont supérieurs à 1. Laissez le nombre généré dans la plage. Que le nombre minimum soit min, et laissez le nombre maximum être max. Avec ceux-ci, afin de convertir le nombre entre 0 et 1, utilisez la formule:
random_number = (num - min) / (max - min)

random_number devrait maintenant être compris entre 0 et 1.
Les questions suivantes sont de savoir comment générer des nombres aléatoires et comment décider Min et Max. En fait, les nombres aléatoires, tels que décrits par les spécifications C ++ 20, sont en fait des nombres pseudo-aléatoires. La spécification C ++ 20 donne un guide pour produire des nombres vraiment aléatoires (nombres aléatoires non déterministes). Le problème avec ce générateur de nombres vraiment aléatoires est que la responsabilité du compilateur, ou le programmeur, est de fournir l'algorithme à ce qui est considéré comme une génération de nombres aléatoires non déterministes. Cet article ne traite pas de nombres aléatoires non déterministes.

Les nombres pseudo-aléatoires sont générés dans une séquence (un ordre) de nombres, qui ressemblent à des nombres aléatoires. La génération d'un nombre aléatoire a besoin de ce qu'on appelle une graine. La graine est une valeur de départ. Cet article explique les bases de la génération de nombres aléatoires dans C ++ 20. Si le nombre résultant est supérieur à 1, il est ramené entre 0 et 1, en utilisant la formule ci-dessus. La bibliothèque C ++ doit être incluse dans le programme pour avoir une séquence de nombres aléatoires ou aléatoires.

Contenu de l'article

  • Distribution
  • linear_congruential_engine
  • Default_random_Engine
  • Cours de distribution de nombres aléatoires
  • Meilleur nombre aléatoire
  • Conclusion

Distribution
Distribution uniforme

Une distribution uniforme est celle où la probabilité d'un nombre est celle du nombre total de nombres dans la séquence. Considérez la séquence suivante:

0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100

Si ces onze nombres sont une séquence de nombres aléatoires, chaque nombre est apparu une fois sur onze occurrences. Cela signifie que c'est une distribution uniforme. En pratique, tout ne peut pas apparaître une fois. Un ou deux ou trois peuvent apparaître plus d'une fois, et ils n'apparaîtraient pas dans l'ordre régulier.

Si le nombre aléatoire renvoyé est de 40, le programme doit convertir le nombre aléatoire entre 0 et 1 en utilisant

random_number = (40 - 0) / (100 - 0)
= 4/10 = 0.4

Ici, num est 40; min est 0 et max est 100.

Distribution binomiale

La distribution binomiale n'est pas une distribution uniforme. «Bi», le préfixe du binomial, signifie deux. Le nombre de valeurs dans la distribution binomiale est représenté par t en c++. Si les chiffres BI concernés pour la distribution sont 2 et 3, et si t est 1, alors la séquence est:

2, 3

Si t est 2 pour les mêmes nombres BI (2 et 3), alors la séquence devient,

4, 12, 9

Si t est 3 pour les mêmes nombres BI (2 et 3), alors la séquence devient,

8, 36, 54, 27

Si t est 4 pour les mêmes nombres bi (2 et 3), alors la séquence devient,

16, 96, 216, 216, 81

T est un entier positif qui peut être supérieur à 4. Pour chaque valeur de T, il y a des éléments T + 1 dans la séquence. Une séquence dépend des nombres Bi choisis et de la valeur de t. Les nombres bi peuvent être n'importe quelle paire, e.g., 13 et 17. La somme des nombres BI est également importante. Une séquence est développée à partir de ce que l'on appelle le théorème binomial.

Il y a d'autres distributions dans la bibliothèque aléatoire en C++.

linear_congruential_engine

Il existe un certain nombre de moteurs à nombres aléatoires en C++. linéaire_congrueential_ngine en fait partie. Ce moteur prend une graine, le multiplie avec un multiplicateur et ajoute un nombre constant C au produit pour avoir le premier nombre aléatoire. Le premier nombre aléatoire devient la nouvelle graine. Cette nouvelle graine est multipliée par le même «A», dont le produit est ajouté au même C, pour avoir le deuxième nombre aléatoire. Ce deuxième nombre aléatoire devient la nouvelle graine du prochain numéro aléatoire. Cette procédure est répétée pour autant de nombres aléatoires que requis par le programmeur.

La graine ici a le rôle d'un indice. La graine par défaut est 1.

Une syntaxe pour la linéaire_congruential_engine est:

linear_congruential_enginelce

LCE est le nom du choix du programmeur. Cette syntaxe utilise la graine par défaut de 1. Le premier paramètre de modèle ici doit être spécialisé avec «unsigned int». Les deuxième et troisième devraient avoir les valeurs réelles de «A» et C. Le quatrième devrait avoir la valeur réelle du nombre aléatoire maximal attendu, plus 1.

En supposant qu'une graine de la valeur 2 est requise, alors la syntaxe serait:

linear_congruential_enginelce (2)

Notez la graine entre parenthèses juste après lce.

Le programme suivant, illustre l'utilisation de linear_congrueential_ngine, avec la graine par défaut de 1:

#inclure
#inclure
Utilisation de Namespace Std;
int main()

linear_congruential_enginelce;
couter <couter <couter <couter <couter <couter <couter <couter <retour 0;

La sortie est:

4
13
40
121
364
0
499

Notez la façon dont l'objet LCE du moteur a été instancié. Ici, «A» est 3, C est 1, et le maximum, espérait atteindre le nombre, M est 500. M est en fait un module - voir plus tard. LCE (), comme utilisé ici, n'est pas un constructeur. Il s'agit d'un opérateur qui renvoie le prochain numéro aléatoire requis pour le moteur dans la séquence de sortie. Min pour ce schéma est 0, et max est 499, et ceux-ci peuvent être utilisés pour convertir un nombre renvoyé entre 0 et 1 - voir ci-dessous.

Le premier numéro aléatoire renvoyé est 4. Il est égal à 1 x 3 + 1 = 4. 4 devient la nouvelle graine. Le nombre aléatoire suivant est de 13, ce qui est égal à 4 x 3 + 1 = 13. 13 devient la nouvelle graine. Le nombre aléatoire suivant est de 40, ce qui est égal à 13 x 3 + 1 = 40. De cette façon, les nombres aléatoires suivants sont de 121 et 364.

Le code suivant, illustre l'utilisation de linear_congrueential_engine, avec une graine de 2:

linear_congruential_enginelce (2);
couter <couter <couter <couter <couter <couter <couter <couter <

La sortie est:

7
22
67
202
607
0
999

Le nombre aléatoire maximal espéré ici est 1000. Min pour ce schéma est toujours 0, et Max est maintenant 999, et ceux-ci peuvent être utilisés pour convertir un nombre renvoyé entre 0 et 1 - voir ci-dessous

Le premier numéro aléatoire renvoyé est 7. Il est égal à 2 x 3 + 1 = 7. 7 devient la nouvelle graine. Le nombre aléatoire suivant est 22, ce qui est égal à 7 x 3 + 1 = 22. 22 devient la nouvelle graine. Le nombre aléatoire suivant est de 67, ce qui est égal à 22 x 3 + 1 = 67. De cette façon, les nombres aléatoires suivants sont 202 et 607.

Le code suivant utilise la formule ci-dessus pour produire un nombre aléatoire entre 0 et 1, pour ce moteur:

linear_congruential_enginelce (2);
unsigned int num = lce (); // Nombre aléatoire normal
non signé int min = lce.min ();
unsigned int max = lce.max ();
float random_number = ((float) (num - min)) / ((float) (max - min));
couter <

La sortie est:

0.00700701

Ici, num a 7, et donc

random_number = (7 - 0) / (999 - 0) = 7/999 = 0.00700701 arrondi à 8 décimales.

linear_congrueential_ingine n'est pas le seul moteur spécialisé dans la bibliothèque aléatoire; Il y en a d'autres.

Default_random_Engine

C'est comme un moteur à usage général. Il produit des nombres aléatoires. L'ordre de séquence n'est pas garanti d'être non déterminé. Cependant, l'ordre n'est probablement pas connu du programmeur. Les deux lignes suivantes montrent comment ce moteur peut être utilisé:

random_device rd;
Default_random_Engine Eng (rd ());

Random_device est une classe à partir de laquelle RD a été instancié. Notez les parenthèses pour RD dans les listes d'arguments du moteur. Un distributeur a besoin de ce moteur pour son fonctionnement - voir ci-dessous.

Cours de distribution de nombres aléatoires
uniforme_int_distribution

uniforme_int_distribution
La probabilité qu'un nombre se produira est 1 divisé par le nombre total de nombres pour cette classe. Par exemple, s'il y a dix nombres de sortie possibles, la probabilité que chaque nombre est affiché est 1/10. Le code suivant illustre ceci:

random_device rd;
Default_random_Engine Eng (rd ());
uniforme_int_distributiondist (3, 12);
couter <couter <

La sortie de l'ordinateur de l'auteur est:

9 8 3 5 12
7 4 11 7 6

Malheureusement, 7 est apparu deux fois au détriment de 10. Les arguments de DIST sont les nombres 3 et 13 inclus (dix entiers consécutifs). DIST (ENG) est un opérateur qui renvoie le numéro suivant. Il utilise le moteur. Notez l'utilisation de la spécialisation du modèle int.

Il n'est pas nécessaire de rechercher Num, Min et Max pour ce cas, puis utiliser la formule ci-dessus pour obtenir un nombre entre 0 et 1. En effet. La sortie ne sera pas la même pour chaque exécution.

uniforme_real_distribution

uniforme_real_distribution est similaire à Uniform_int_distribution. Avec lui, afin d'obtenir un nombre entre 0 et 1, utilisez simplement 0 et 1 comme arguments. Le code suivant illustre ceci:

random_device rd;
Default_random_Engine Eng (rd ());
uniforme_real_distributiondist (0, 1);
couter <couter <

La sortie de l'ordinateur de l'auteur est:

0.384051 0.745187 0.364855 0.122008 0.580874
0.745765 0.0737481 0.48356 0.184848 0.745821

Remarque l'utilisation de la spécialisation du modèle de flotteur. La sortie ne sera pas la même pour chaque exécution.

distribution binomiale

Avec cette distribution, la probabilité de chaque nombre de sortie n'est pas la même. Binomial_distribution a été illustré ci-dessus. Le code suivant montre comment utiliser le binomial_distribution pour produire 10 nombres aléatoires:

random_device rd;
Default_random_Engine Eng (rd ());
distribution binomialedist (10);
couter <couter <

La sortie de l'ordinateur de l'auteur est:

5 3 5 5 7
6 6 5 8 3

La sortie ne sera pas la même pour chaque exécution. La spécialisation du modèle utilisé ici est int.

Le code suivant utilise la formule ci-dessus pour produire un nombre aléatoire entre 0 et 1, pour cette distribution:

random_device rd;
Default_random_Engine Eng (rd ());
distribution binomialedist (10);
non signé int num = dist (Eng); // Nombre aléatoire normal
non signé int min = dist.min ();
non signé int max = dist.max ();
couter <couter <couter <couter <float random_number = ((float) (num - min)) / ((float) (max - min));
couter <

La sortie de l'ordinateur de l'auteur est:

0
dix
7
0.7

Meilleur nombre aléatoire

Le nombre de secondes depuis que l'époque Unix peut être utilisée comme graine. Il devient difficile pour le pirate de connaître la graine. Le programme suivant l'illustre avec le linéaire_congrualiente_engine:

#inclure
#inclure
#inclure
Utilisation de Namespace Std;
int main()

const auto p1 = chrono :: system_clock :: maintenant ();
unsigned int seed = chrono :: durée_cast(P1.Time_Since_Epoch ()).compter();
linear_congruential_enginelce (semence);
couter <couter <couter <couter <retour 0;

La sortie de l'ordinateur de l'auteur est:

91 274 823 470 411
0
999

Notez que la bibliothèque Chrono a été incluse. La sortie est différente pour chaque exécution.

Conclusion

La façon la plus simple d'avoir un nombre aléatoire entre 0 et 1 est d'utiliser le random_device, le default_random_engine et le uniforme_real_distribution (avec les arguments 0 et 1). Tout autre moteur ou distribution utilisé peut avoir besoin de la formule, random_number = (num - min) / (max - min).