Blog Alphorm Logo de blog informatique spécialisé en technologie et solutions IT
  • Développement
  • 3D et Animation
  • Cybersécurité
  • Infrastructure
  • Virtualisation
  • Réseaux
  • Bureautique
  • BDD
En cours de lecture : Les fonctions aléatoires de la bibliothèque random en C++ 11
Agrandisseur de policeAa
Blog AlphormBlog Alphorm
  • Développement
  • 3D et Animation
  • Cybersécurité
  • Infrastructure
  • Virtualisation
  • Réseaux
  • Bureautique
  • BDD
Search
  • Développement
  • 3D et Animation
  • Cybersécurité
  • Infrastructure
  • Virtualisation
  • Réseaux
  • Bureautique
  • BDD
Suivez-nous
© Alphorm 2024 - Tous droits réservés
CybersécuritéDéveloppement

Les fonctions aléatoires de la bibliothèque random en C++ 11

Fabien Brissonneau Par Fabien Brissonneau 18 janvier 2025
Partager
1e lecture en min
Partager

La librairie standard a été étoffée avec l’arrivée de la version 11 du C++. Pour la gestion des fonctions aléatoires, nous avons aujourd’hui à disposition une bibliothèque assez complète qui suit bien mieux les standards C++ que le bon vieux rand(). Dans cet article, je vous présente sans prétention les alternatives à rand() et consort, telles qu’elles devraient être implémentées. Si votre compilateur ou environnement ne supporte pas C++11 complètement, et c’est tout à fait possible, les codes suivants ne compileront pas.

Un tirage aléatoire avec rand

Pour utiliser rand(), il faut disposer de la bibliothèque cstdlib : #include <cstdlib>

				
					for   (int  i  =  0;  i   <  10;  i++)

{

           int  valeur = rand()

          std::cout<< "valeur rand" << valeur << std::endl;

}
				
			

Pour un résultat :

Table de matière
Un tirage aléatoire avec rand Un tirage aléatoire avec la bibliothèque randomConclusionEn Résumé :
image d'infrastructure IT moderne représentant un serveur et des connexions réseau

Nous remarquons tout d’abord que les tirages aléatoires sont toujours les mêmes. Ensuite que nous n’avons pas borné le tirage.

Pour obtenir des tirages qui sont différents à chaque lancement, il faut initialiser la série aléatoire :

				
					srand((unsigned int)time(0));

for  (int  i  =  0;  i  <  10;  i++)

{

        int valeur  = rand();

       std:: cout   << "valeur rand "  << valeur <<std::endl;

}
				
			

L’utilisation de time ici permet d’initialiser la série avec une graine qui dépend du temps, donc variable avec les exécutions. Ne pas oublier l’include #include <ctime>. Le transtypage n’est nécessaire que pour faire taire le compilateur qui se plaint sur les types unsigned int et time_t. Le type time_t est sur mon compilateur compatible avec unsigned int, mais ce n’est pas garanti par la norme.

Enfin, pour obtenir des valeurs entre 1 et 6 (comme pour un dé classique), je rajoute le code suivant :

Diagramme des fonctions informatiques en entreprise pour optimisation des processus IT
				
					srend((unsigned int)time(0));

for   (int  i  =  0;  i   <  10;  i++)

{

        int valeur  = rand()%6   +1;

      std::cout  <<  "valeur  rand "  <<  valeur  <<  std::endl;

}
				
			

Les valeurs vont de 1 à 6 inclus. Le tirage n’est pas excellent en terme d’aléatoire, il serait sans doute meilleur d’utiliser RAND_MAX pour calculer la valeur entre 1 et 6.

 

Un tirage aléatoire avec la bibliothèque random

Utilisant la dernière version de C++, vous pouvez mettre en œuvre la biliothèque random.

En utlisant #include <random>, vous accédez aux classes de cette bibliothèque.

Il y a essentiellement 2 catégories de classes indispensables : les moteurs de génération aléatoire et les distributions. Le moteur de génération, comme son nom l’indique, produit des séries de nombres pseudo-aléatoires (utilisant une graine à fournir), et les distributions accommodent ces séries suivant les lois classiques : uniformes, de Bernoulli, de Poisson ou normales.

Le choix du moteur de génération se fait en fonction de considérations de rapidité et d’occupation mémoire. Les algorithmes proposés par la norme sont : linear_congruential_engine, mersenne_twister_engine et subtract_with_carry_engine. Ces classes sont des template, donc paramétrables. Il y a aussi des adaptateurs de moteur de génération, qui utilisent les moteurs décrits ci-dessus, mais qui altèrent certaines caractéristiques.

Enfin, des générateurs classiques, basés sur les moteurs ci-dessus, sont proposés. Ce sont ces moteurs là que la plupart d’entre nous vont utiliser. Pour la définition exacte des algorithmes utilisés, je vous laisse vous reporter à la documentation : minstd_rand0, minstd_rand, mt19937, mt19937_64, ranlux24_base, ranlux48_base, ranlux24, ranlux48, knuth_b et default_random_engine. Ce dernier est dépendant de l’implémentation de votre bibliothèque.

Pour faire un tirage, il faut choisir un moteur (ou bien paramétrer le vôtre) et choisir une distribution. Le code suivant permet par exemple un tirage entre 1 et 6, suivant une distribution équiprobable entre ces bornes.

				
					std :: default_random_engine  re;

std::uniform_int_distribution<int> distrib{  1.  6  };

for  (int i  =  0;  i  <  12;  i++)  {

        std:: cout << distrib(re)  <<  std::endl;

}
				
			

Nous retrouvons dans le cas le même problème d’initialisation de la série aléatoire que précédemment avec rand(). Pour initialiser la série, il faut fournir un paramètre au moteur de génération. Par exemple le temps.

				
					std:: default_random_engine  re(time(0));

std::uniform_int_distribution<int> distrib{  1,  6  };

for  (int  i  =  0;  i  <  12;  i++)  {

        std::cout  <<  distrib(re)  << std::endl;

}
				
			

Si vous voulez le faire avec la bibliothèque chrono (standard C++11), voici le code à écrire, en n’oubliant pas l’include : #include<chrono>

				
					std::default_random_engine re(std::chrono::system_clock::now().time_since_epoch().count());

std:uniform_int_distribution<int> distrib{  1,  6  };

for  (int  i  =  0;  i  <  12;i++)  {

           std::cout  << distrib(re)  <<  std::endl;

}
				
			

Enfin, pour simplifier les tirages, on peut utiliser bind (standard). Voici le code à écrire, ne pas oublier l’include #include <functional>. Ce code n’apporte rien au tirage lui-même, mais peut vous simplifier la vie pour les appels.

				
					std::default_random_engine re(std::chrono::system_clock::now().time_since_epoch().count());

std::uniforme_int_distribution<int> distrib{1,   6    };

auto rd =  bind(distrib,  re);

for    (int    i=    0;   i    <   12;i++)     {

          std::cout    <<    rd()  <<  std::endl;
          
          }
				
			

Finissons avec une implémentation d’une classe Dé à 6 faces.

				
					]class   De   {

   public  :

            std::default_random_engine   re;

           std::uniform_int_distribution<int>  distrib{  1,   6   };

 ]       De()

          :re(std::chrono::system_clock::now().time_since_epoch().count())  {

          }

]       int rouler()    {

                    return distib(re);

           }

};
				
			

Faites rouler le dé et vous obtenez un tirage aléatoire 😉

Conclusion

D’un façon générale, la bibliothèque random du C++11 est bien meilleure en terme d’aléatoire que la bonne vieille fonction rand(). Mais elle propose surtout beaucoup plus de possibilités de paramétrage. En utilisant ce qui est déjà configuré en terme de moteur et de distribution, vous avez de quoi couvrir pas mal de besoins. Il est conseillé, sauf si vous avez réellement des besoins spécifiques, d’utiliser le moteur pas défaut.

En Résumé :

  1. Nouveautés en C++11 : Introduction aux avancées de C++11, en particulier pour la génération aléatoire.
  2. Bibliothèque de Génération Aléatoire : Exploration de la bibliothèque standard C++11 pour l’aléatoire.
  3. Illustration Pratique : Exemples de codes démontrant l’utilisation des fonctions aléatoires.
  4. Guides d’Utilisation : Astuces et contextes d’application des fonctions aléatoires C++11.

Facebook
Twitter
LinkedIn
Email
WhatsApp
Par Fabien Brissonneau
Expert en Conception et Développement sur Java et DotNet avec 15 Ans d'Expérience
Fabien, expert en développement, conception et architecture sur les plateformes Java et DotNet, offre ses services depuis plus de 15 ans. Fort de son expérience en C++, il excelle également dans le domaine de la mobilité, ayant créé avec succès des outils pour Android et Windows Phone, certains étant même publiés. En plus de son travail, il consacre une part significative de son temps à la formation, partageant ainsi son expertise avec les acteurs clés de l'industrie. Pour tout ce qui concerne la conception orientée objet sur les plateformes Java et DotNet, Fabien est votre expert de confiance.

Derniers Articles

  • Techniques pour gérer les fichiers texte en C#
  • Créer et lire un fichier CSV avec C#
  • JSON : Comprendre et Utiliser Efficacement
  • Créer une Base SQLite dans C#
  • Lecture des données SQLite simplifiée
1 commentaire 1 commentaire
  • Drouillon dit :
    17 janvier 2019 à 12 h 14 min

    Votre exposé est très bien fait et très clair ce qui m’amène à vous demander conseil. Je viens de publier un livre sur le C++ aux éditions ENI (« Langage C++, L’héritage du C et la programmation orientée objet »). Il s’agit d’un livre qui s’adresse à des débutants et j’aimerais beaucoup avoir l’avis de personnes qui comme vous connaissent le C++ avec à l’évidence une compétence pédagogique. Jusqu’à maintenant ce livre est assez mal accueilli par la communauté C++. Il faut dire que je n’en fais pas partie, à l’origine je suis artiste numérique et pour moi le programmeur est d’abord un écrivain. Ce que j’aime c’est explorer un langage avec ses possibilités de sens. Mon livre n’est certes pas parfait. J’ai pensé que peut-être vous pourriez m’aider à pointer des axes d’améliorations. En vous remerciant,

    Connectez-vous pour répondre

Laisser un commentaire Annuler la réponse

Vous devez vous connecter pour publier un commentaire.

Blog Alphorm
  • Développement
  • 3D et Animation
  • Cybersécurité
  • Infrastructure
  • Virtualisation
  • Réseaux
  • Bureautique
  • BDD
En cours de lecture : Les fonctions aléatoires de la bibliothèque random en C++ 11

© Alphorm - Tous droits réservés