Mini Tuto : L'aléatoire en C++11

Mort a rand() !

a marqué ce sujet comme résolu.

Bonjour tout le monde ! Je viens vous parler du tuto que j'ai réalisé hier, qui porte sur l'aléatoire en C++11. C'est mon premier tutoriel, donc il risque de contenir :

  • De l'humour de merde
  • Des imprécisions
  • Des fautes d’orthographes
  • Des erreurs (eh oui mes connaissances dans le sujet ne sont pas non plus extrêmes …)

Je l'ai fait dans l'objectif d'avoir une réponse toute prête à donner aux débutants qui utilisent rand() en C++, mais aussi dans l'objectif de synthétiser mes connaissances, et d'apporter un tuto supplémentaire au zds pour qu'il ait plus de contenus "exclusifs" (même si c'est pas grand chose). Bref vous pouvez le retrouver ICI.

Je serais ravi d'avoir vos avis S'il vous plait je vous en supplie dite moi ce que je dois changer pour que ce tuto soit acceptable ! :lol:

Bref, si le littéraire qui est en vous a envie de corriger des fautes d’orthographes, ou que l'expert en C++ que vous êtes a envie de me corriger sur certains points ou termes techniques, voir même a envie d'enrichir le tutoriel de ses connaissances (par exemple en faisant les chapitres que j'ai mis dans le : A faire, et évidemment dans ce cas là je le rajouterais en rédacteur du tutoriel :) ), ce sera avec plaisir !

J'attends vos commentaires / critiques (constructives de préférence), merci d'avance pour votre aide ! ;)


PS : Le tutoriel est aussi en validation, par choix, parce que pour tout vous dire … Je n'avais même pas remarqué la présence de ce forum au début et donc je souhaiterais mettre ce qui a été déjà fait en libre accès le plus tôt possible ! J'espère que vous approuverez mon choix !

+2 -0

Je vais lire ça en détail ;) Mais déjà, j'aime pas le style SdZ ("je me pose une question, je répond à ma propre question, je suis complètement schyzophrène…) :D

Introduction : commencer en comparant avec rand() n'est pas forcement une bonne idée. Ca donne l'impression que le C++11 avait envie de changer sans raison valable. A la base, il y a de nouvelles fonctions parce que :

  • rand() pose des problèmes d'utilisation (distribution non uniforme si mal utilisée)

  • les nouvelles fonctions sont plus puissantes (plusieurs algorithmes de génération de nombres pseudo-aléatoires utilisables, plusieurs distributions utilisables)

Avant de commencer avec les fonctions du C++, je verrais bien un chapitre (rapide) sur la génération de nombre pseudo-aléatoire (en particulier pourquoi "pseudo" ? pourquoi plusieurs algos de génération ? qu'est-ce qu'une distribution ?)

Comment générés plusieurs fois la même série de nombres pseudo-aléatoires ? (utiliser une graine fixée)

Montrer des figures de distributions (tu peux prendre celle de Wikipédia ou je peux te les faire avec R)

En tout cas, très bonne initiative !

+1 -0

Merci ! Ça me fait plaisir ! :) C'est vrai que j'ai un style de schizophrène faut me pardonner c'est parce que je le suis

Pour rand() tu veut dire que ce n'est pas assez "hasardeux" ? :lol:

Je pense que je vais modifier mon intro en effet pour expliquer pourquoi abandonner rand(), par contre pour le chapitre rapide sur la génération de nombre, je ne vois pas trop comment m'y prendre (en plus je ne saurait pas expliquer la présence de plusieurs algo de générations :-° )

Pour générer plusieurs fois la même série, je le sous entend à un moment (je dis que garder la même graine ferait que la série ne changera pas), par contre j'ai du mal a voir une utilité a ça (a part pour retrouver exactement une configuration quoi …), t'aurait un exemple ?

En tout cas merci pour tes conseils ! Je vais essayer d'améliorer tout ça ! Si tu veut aider directement je peut te rajouter en auteur ! ;)

+0 -0

Salut,

PS : Le tutoriel est aussi en validation, par choix, parce que pour tout vous dire … Je n'avais même pas remarqué la présence de ce forum au début et donc je souhaiterais mettre ce qui a été déjà fait en libre accès le plus tôt possible ! J'espère que vous approuverez mon choix !

Pour tout te dire, je ne suis pas valido à la base (j'aurai du mal a trouver tes fautes), mais comme je maîtrisais le sujet, j'y ai jeté un oeil. J'ai repéré plusieurs problèmes qui empêcheront de le publier en l’état, sur la forme (je vais te les citer en dessous). Par contre ce qui m'a gêné en première lecture c'est surtout le fond que je trouve très très léger. En particulier tu n'explique pas grand chose de toutes les notions sous-jacente, te contenant, en gros, de reproduire une bête fonction rand() "à la C++11" (alors que la lib permet bien plus que ça).

Je suis arrivé à ta conclusion où tu dis alors :

Disclaimer : Ce tutoriel vise un public de débutant, et n'explique pas le fonctionnement interne / les notions mathématiques requises pour comprendre l'aléatoire ! C'est un tutoriel pour ingénieur, ça marche, on ne sait pas comment mais on est content

Techniquement ça peut se défendre. Je pense dommage de faire un tuto sur ce sujet sans en expliquer le fond mais j'avoue que ça pourrait aider certains de savoir comment on fait pour générer des nombres aléatoires sans ce taper 3 paragraphes sur ce qu'est une distribution de probabilité.

Donc, pour information, j'ai demandé l'avis a mes collègues staff, habitués à la validation, ce qu'ils en pensaient. Je te tiendrais informé. La communauté peut aussi donner son avis ici !


Concernant la forme, voici quelques remarques (dans le désordre et rapidement, j'ai dut en oublier) :

  • Tu abuse beaucoup trop de la balise Question. Il y en a partout ce n'est pas très agréable à lire. La forme Question/Réponse en rédaction est rapidement usante. Tu peux le garder pour les questions évidente du lecteur mais ça ne devrait pas te servir de fil conducteur pour ton contenu.
  • Ton dernier code ne compile probablement pas (il manque un using namespace std ou des std:: devant les cout et endl). D'une manière général pense à indenter ton code pour le rendre un poil plus clair (même si j'avoue que ici c'est tellement court que ce n'est pas gênant).
  • Dans l'intro, la prochaine norme ce n'est pas C++11y mais C++1y (le y sera remplacé par l'année de sa sortie). Tu peux même déjà nommer le C++14 puisque il est en cours de finalisation et que le comité le nomme déjà ainsi.
  • Il manque des balises de codes inline pour des types C++ notamment dans la partie sur random_device
  • dans la section "Le générateur arrive !" il y a une liste qui n'est pas mise en forme correctement dessous "Et donc, lequel va t'on choisir ?")
  • La partie sur les générateur et en particulier sur mt19937 est plus que contestable. mt19937 est un type, cout est une instance. C'est différent. Déjà que dire que cout est instancié par "les créateurs de la lib standard" est limite, pour mt19937 c'est faut. Ils ont juste définit un alias de type avec des paramètres par défauts. Mais c'est bien toi qui crée l'instance.

Bon je vais arrêter là.


Voila pour un premier retour qui je l'espère constructif. J'ai essayé de détailler mes remarques puisque c'est ton premier tuto, il ne faut pas le prendre personnellement. Le sujet peut largement convenir pour un mini-tuto comme ça. Ce qui me gène le plus est qu'effectivement on reste sur notre faim mais comme je l'ai dit plus haut, ça pourrait être utile à certaines personnes. Cependant dans un tel cas je me demande si le snippet de code dans un FAQ ne serait pas suffisant. Si j'ouvre un tuto portant uniquement sur ce module du C++11, je m'attendrais à plus de contenu (mais c'est un avis personnel).

Merci beaucoup pour tes retours ! :)

Pour le problème des balises questions je ne sait pas trop si je vais changer, ça me ferait réécrire une bonne partie du tutoriel (pas dans le fond mais dans la forme), pour peut-être arriver a un résultat pas génial (je dis ça parce que le coup des questions réponses m'est venu naturellement, c'est dans mon style littéraire ! :lol: )

  • Pour le dernier code merci de l'avoir signalé, quand j’avais voulu le compiler j'avais du rajouter le using namespace et j'ai oublié de le corriger dans le tuto ! Je le rajoute dès que j'ai un peu de temps ! ;)
  • Je corrigerais et mettrais C++14 ! ^^
  • Balises de code inline ? Kezako ?
  • Ok je la mettrais en forme !

Pour le mt19937, j'ai peut-être pas été très clair, mais je me cite : " ils nous ont aussi fait un mersenne_twister_engine aux paramètres template déjà tout prêt du joli nom de mt19937. Nous allons donc nous instancier un mt19937 pour faire de l'aléatoire !". Je vais essayer de rendre ça plus clair / explicite !

Merci pour tes retours, ils sont tous constructifs ne t'inquiète pas ! Et puis c'est moi qui ait demandé de l'aide ! ;)

Donc sur 2 avis, il y en a 2 qui me disent que ce serait bien d'aller plus en profondeur … Bon, je vais essayer mais je ne vous promet rien (c'est pas comme si j'avais un niveau lycée en proba et stats quoi … :-° )

+0 -0

Bon, je vais essayer mais je ne vous promet rien (c'est pas comme si j'avais un niveau lycée en proba et stats quoi … :-° )

Il parait qu'on voit les distributions maintenant, si tu connais le principe, c'est déjà pas mal et à mon avis suffisant pour expliquer l'idée. Si tu as des questions sur l'aspect math, je dois pouvoir te filer un coup de main au cas où (et je suis probablement pas le seul).

Sinon, je rejoins le point de vue de Kje, quand je tombe là-dessus, j'en attends plus sur l'intérêt de ces fonctions et ce qu'on peut faire avec. Je parle ici en tant que membre et non au nom du staff.

+1 -0

Ok @dri1, je veut bien un coup de main, j'ai une vague idée de ce qu'est une distribution, mais je ne me sens aps en mesure d'expliquer a quelqu'un ce que c'est ! :lol:

@pierre_24 Je ne comprend pas vraiment que tu veut dire ? Auquel de mes posts est ce que tu réponds ? :)

+0 -0

Je parle de ton tutoriel. Lorsque tu l'as créé, tu a rédigé le texte dans le champ "introduction" de celui-ci. En fait, la "bonne manière" de rédiger un tutoriel sur le ZdS, c'est d'employer ce champ pour y mettre l'introduction, puis ensuite, sur la droite, tu as "ajouter un extrait". Tu ajoutes autant d'extraits que tu as de titre de niveau 1, et dedans, tu mets le texte correspondant :)

ça te permet de fragmenter ton mini-tuto en sous-parties (qui restent sur la même page) qui sont reprises dans un sommaire, plus facilement accessible. Hésite pas à demander plus d'infos si ça te parrait compliqué ;)

Déja, c'est une classe template, il faudrait aussi préciser ses paramètres de template ! Ensuite, est ce que vous avez déjà entendu parler de cout … ?

Pourquoi je demande ça ? Parce que cout est déjà instancié pour nous ! Et qui est-ce qui a instancié cout … ?

Les créateurs de la lib standard bien sur ! Et vu qu'ils sont malins, ils nous ont aussi fait un mersenne_twister_engine aux paramètres template déjà tout prêt du joli nom de mt19937. Nous allons donc nous instancier un mt19937 pour faire de l'aléatoire ! C'est parti !

Il n'y a aucun rapport. std::cout est un std::ostream, instancié probablement dans iostream. std::mt19937 c'est juste un type.

Je suis d'accord avec pas mal de monde ici, il y a moyen de faire un tuto un peu plus trapu, plus ambitieu. Le gros soucis, c'est que ton tuto, en l'état, n'apporte rien de plus que la page du constructeur de std::mt19337. Rien que d'expliquer à quoi servent les paramètres template devraient te prendre un bon chapitre ^^. Il suffit de voir le typedef pour s'en convaincre.

1
2
3
typedef mersenne_twister_engine<uint_fast32_t,
  32,624,397,31,0x9908b0df,11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253>
  mt19937;

D'autre part, il y a un peu trop de rectangles bleus.

Ton tutoriel est donc chouette pour un débutant qui veut récupérer des nombres aléatoires pour son jeu du plus ou moins. Si c'est la cible que tu vise, inutile de faire un tuto si long (En fait, un simple tour sur la page du constructeur suffirait). Sinon, je t'encourage à complexifier ton cours. J'attends avec impatience la prochaine mise à jour, en particulier pour l'aléatoire entre des bornes non contiguës

Alors vu que j'ai eu beaucoup de remarque je vais décaler ce chapitre à d'autres mise a jour, en attendant je vais faire des maj correctives ! :-°

C'est si génant que ça les questions / réponses ? JBon bah je crois que je vais les enlever alors …

Sinon pour mt19937 je dis bien qu'on va en instancier un non ? :lol: Je vais changer ce passage, mon objectif c'était de faire comprendre que le boulot avait été déja fait en parti, mais bon c'est vrai qu'il est pas génial ! Merci de ton retour ! ;)

+0 -0

Pour générer plusieurs fois la même série, je le sous entend à un moment (je dis que garder la même graine ferait que la série ne changera pas), par contre j'ai du mal a voir une utilité a ça (a part pour retrouver exactement une configuration quoi …), t'aurait un exemple ?

valent20000

J'en vois 2 (qui sont assez spécifique, effectivement, l'utilité est limité) :

  • quand tu donnes des explications utilisant des nombres aléatoires (par exemple pour un cours en ligne), tu peux utiliser une graine spécifique pour que les élèves aient les mêmes résultats que toi.

  • quand tu fais des tests unitaires avec des nombres aléatoires, cela peut être bien d'utiliser plusieurs fois la même graine quand tu rencontres un problème

Pour montrer que l'approche C++11 est plus évolutive que rand(), tu peux peut-être montrer comment on implémente un générateur et une distribution ? (même des algos simples, le but est de montrer l'API).

Une idée de plan plus complet :

  • Introduction. Pourquoi une évolution des fonctions de génération de nombres pseudo-aléatoires en C++11 ? Pourquoi "pseudo-aléatoire" ? Exemple de code en C++11 (si un débutant est intéressé que par le code, il pourra arrêter la lecture après l'introduction). Qu'est qu'une graine, un générateur, une distribution ? (c'est une introduction, chaque "réponse" à ce question doit tenir sur 1 ou 2 phrases. Le reste est détaillé dans la suite).

  • théorie de la génération des nombres aléatoires. Problématiques ? Limitations ?

  • La graine. Quel est son rôle ? Comment la générer ? Quand la générer (faut-il la générer une fois ou plusieurs fois) ?

  • les générateurs. Quel est son rôle ? Quels sont les générateurs proposés par la STL ? Comment les utiliser ? Comment créer d'autres générateurs ?

  • les distributions. Mêmes questions que pour les générateurs.

  • Aller plus loin. Lectures complémentaires ? Autres bibliothèques de génération de nombres aléatoires. Problèmes spécifiques selon les domaines (génération de nombres aléatoires en parallèle, utilisation de cuRand, etc. Peut être faire un chapitre spécifique sur la génération parallèle ?). Applications des nombres aléatoires (Monte Carlo, cryptographie, etc) -> le but de cette partie est de montrer qu'il y a d'autres choses non abordés dans ce tuto et orienté le lecteur vers des lectures complémentaires.

Remarque : l'intérêt d'écrire un tuto, c'est aussi d'améliorer ses connaissances. Il ne faut pas avoir peur de faire quelques recherches complémentaires, prendre son temps pour rassembler suffisamment d'informations et ne pas s'arrêter à la page de doc de cppreference.com ;)

+1 -0

quand tu fais des tests unitaires avec des nombres aléatoires, cela peut être bien d'utiliser plusieurs fois la même graine quand tu rencontres un problème

De manière plus général cela permet de rendre un algorithme contenant de l'aléatoire en un algo déterministe ce qui outre figer les tests permet de simplifier le deboguage et rendre un bug plus facilement reproductible. C'est très pratique pour te permettre de reproduire des résultats ce qui est important par exemple dans le monde scientifique.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte