IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Les nombres aléatoires en C [Tutoriel]


Sujet :

C

  1. #1
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut Les nombres aléatoires en C
    http://nicolasj.developpez.com/articles/libc/hasard/

    Au travers de ce tutoriel, je vais vous exposer différentes méthodes pour générer une suite de nombres pseudo-aléatoires. La théorie peut s'appliquer à tous les langages de programmation. Par contre les exemples seront donnés en C.
    Vous pouvez laisser un commentaire sur cet article à la suite.

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par gege2061 Voir le message
    http://nicolasj.developpez.com/articles/libc/hasard/.

    IV. Mettons-y notre grain de sable
    Je ne suis pas du tout d'accord avec cette méthode.

    Que se passe-t-il si il y a plusieurs processus ?

    Et si il y a une autre fonction de génération avec sa propre logique ? Elle va avoir le même mécanisme et réinitialiser elle aussi la graine, sans prévenir ?

    D'une manière générale, les statiques, c'est NON.

    La méthode est connue : Un appel systématique à srand() au début du code (main(), avant toute boucle) et c'est tout.

    Si il y a plusieurs processus, à renouveler à chaque démarrage de processus (fork() etc.). En principe, c'est automatique si srand() est bien placé.

  3. #3
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Je ne suis pas du tout d'accord avec cette méthode.

    Que se passe-t-il si il y a plusieurs processus ?

    Et si il y a une autre fonction de génération avec sa propre logique ? Elle va avoir le même mécanisme et réinitialiser elle aussi la graine, sans prévenir ?

    D'une manière générale, les statiques, c'est NON.

    La méthode est connue : Un appel systématique à srand() au début du code (main(), avant toute boucle) et c'est tout.

    Si il y a plusieurs processus, à renouveler à chaque démarrage de processus (fork() etc.). En principe, c'est automatique si srand() est bien placé.
    Il s'agit d'un tutoriel pour débutant, comme pour les autres, il y a forcement un choix à faire entre être accessible à tous et satisfaire des exigences de développeurs industriels...

    Même la norme C n'impose pas ce genre de chose : avec l'exemple du paragraphe 7.20.2.2 (n1256) peux importe que j'utilise une variable statique...

    Quand j'aurais le temps je rajouterai une note sur la bonne utilisation de srand, en attendant ton commentaires servira d'erratum.


  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par gege2061 Voir le message
    Il s'agit d'un tutoriel pour débutant,
    Justement. Éviter les mauvaises pratiques me semble une priorité. Il y va aussi de la réputation de sérieux du site...

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 99
    Par défaut a propos de la mise a echelle
    Salut,

    Je ne comprends pas bien cette partie :
    Nous obtenons plus de nombres compris entre 0 et 5, pour pallier ce problème, il faut réaliser une "mise à l'échelle" (extrait de la faq FAQ C) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <stdlib.h>
     
    int randomValue = (int)(rand() / (double)RAND_MAX * (N - 1));
    si on prend comme dans l'exemple RAND_MAX = 25 et N = 10, on se retrouve avec les possiblités suivantes :
    25 / 25 * (10-1) = 9
    24 / 25 * (10-1) = 8.64
    23 / 25 * (10-1) = 8.28
    22 / 25 * (10-1) = 7.92
    21 / 25 * (10-1) = 7.56
    20 / 25 * (10-1) = 7.2
    ...
    donc une fois casté on a 9, 8, 8, 7, 7, 7 ...
    On a donc moins de chance d'obtenir un 9 qu'un 7 non?

    ps: je n'ai rien trouvé dans la FAQ pointée au sujet de "mise a l'echelle".

  6. #6
    Invité(e)
    Invité(e)
    Par défaut
    Voici la page dans la FAQ : http://c.developpez.com/faq/?page=al...runif_a_b_reel

    Après, effectivement, il y a quelque chose de louche dans la formule donnée.
    La répartition est bien meilleure avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int randomValue = (int)(rand() / (double)(RAND_MAX-1) * (N));

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 99
    Par défaut
    Merci pour le lien je vais explorer ca. Reste qu'il semble pour le moins difficile d'avoir une repartition totalement egale a partir de rand()

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    La FAQ donne une méthode correcte et un lien vers un document où j'explique comment y arriver et les défauts de quelques méthodes couramment suggérées.

  9. #9
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonsoir,

    dans une future version, il pourrait être intéressant d'introduire d'autres choses :

    • les notions d'indépendance, de discrépance,
    • les outils pour évaluer son générateur (test du chi^2,...)
    • un algo moderne (Mersenne Twister,...).

  10. #10
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Bonsoir,

    dans une future version, il pourrait être intéressant d'introduire d'autres choses :

    • les notions d'indépendance, de discrépance,
    • les outils pour évaluer son générateur (test du chi^2,...)
    • un algo moderne (Mersenne Twister,...).
    Dans un cours de math et non de C alors ...

  11. #11
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Citation Envoyé par Melem Voir le message
    Dans un cours de math et non de C alors ...
    Désolé, j'ai cru qu'il s'agissait d'un cours en C et non d'un cours de C.

  12. #12
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Désolé, j'ai cru qu'il s'agissait d'un cours en C et non d'un cours de C.
    C'est plutôt les deux en même temps. Le but de l'article est clairement deux présenter deux seules fonctions standard de manipulation de nombres aléatoires en C, rand et srand, à savoir comment les utiliser correctement et comment sont-elles implémentées. En effet, la compréhension de leur fonctionnement interne ne peut qu'aider à mieux les utiliser. Dans ce sens, je trouve difficilement envisageable d'ajouter quoi que ce soit d'autre à ce tuto qui est déjà complet, sans remettre en cause l'intérêt d'un second tuto cette fois-ci plus axé sur les maths.

  13. #13
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonsoir,

    Citation Envoyé par Melem Voir le message
    En effet, la compréhension de leur fonctionnement interne ne peut qu'aider à mieux les utiliser.
    Est-ce que vous avez compris quand il ne faut surtout pas les utiliser?

  14. #14
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Est-ce que vous avez compris quand il ne faut surtout pas les utiliser?
    Oui j'ai bien compris. Et vous ?

  15. #15
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour,

    Citation Envoyé par Melem Voir le message
    Oui j'ai bien compris. Et vous ?
    En ce qui me concerne, pas du tout.
    Une mise en garde aborde très succintement la notion de période mais ce terme n'est même pas utilisé :
    Testons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    455
    231
    231
    231
    231
    ...
    C'est plutôt prévisible pour une suite de nombres aléatoires ! Un sujet aussi complexe que le hasard ne peut être résumé par une formule aussi simple. Il existe des contraintes dans le choix des différents paramètres pour éviter ce genre de problème (ce qui, ici, se détecte facilement mais est parfois plus difficilement décelable car visible uniquement pour des valeurs précises de X) :


    • b et c ne doivent pas être multiple l'un de l'autre
    • a-1 doit être un multiple de n, avec n tous les nombres premiers diviseurs de c
    • Si c est multiple de 4, a-1 doit être un multiple de 4
    Même si ces conditions sont réunies, il peut subsister des erreurs, ou plutôt des imperfections au niveau du caractère aléatoire des nombres. Par exemple, si c est une puissance de 2, le bit de poids faible des nombres oscillera successivement entre 0 et 1. De même pour le générateur UNIX :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Xn+1 = ( 1103515245 * xn + 12345 ) % 2147483647
    Même si ce générateur fonctionne correctement, il faut tout de même faire attention : les octets de poids faibles ne sont pas réellement aléatoires.

  16. #16
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    J'ai fait un petit test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    void TestRand(void)
    {
      float N;
      int Tab[10];
      for (int i=0; i<10; i++) Tab[i]=0;
      for (int i=0; i<100; i++)
      {
        N=(float)10.0*rand()/RAND_MAX;
        for (int j=9; j>=0; j--)
        {
          if (N>(float)j) {Tab[j]++; break;}
        }
      }
      for (int i=0; i<10; i++)
      {
        printf("rang %d  %d valeurs\n",i+1,Tab[i]);
      }
    }
    C'est à dire que je calcule 100 valeurs aléatoires flottantes entre 0 et 10 et je compte les résultats.
    Le résultat global me parait correct, si on calcule 1000 valeurs, le résultat me parait excellent.

    Par ailleurs, je ne comprend pas où il serait question de "manipulation" de nombre aléatoire, il s'agit juste de générer des nombres aléatoires.
    Naturellement il est bon d'initialiser le générateur par un appel à randomize().

  17. #17
    Membre émérite Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    Naturellement il est bon d'initialiser le générateur par un appel à randomize().
    Tu voulais certainement dire srand().

  18. #18
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Aleph69 : On voit bien que la valeur 231 se répète sans arrêt là. Faut-il vraiment une phrase où le radical "période" est présent pour que le lecteur le comprenne ? Personnellement, je trouve le commentaire du tutoriel on ne peut plus clair.

    Pierre : Et bin remplace le mot manipulation par génération si ça peut t'aider à ieux comprendre .

  19. #19
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Melem,

    je suis très surpris des propos que vous tenez.
    Pour le moment, l'intérêt d'en discuter avec vous me semble limité car il est évident que vous ne comprenez pas ce que j'écris.
    Je ne vous le reproche pas pour autant.
    Par contre, vous devriez vous documenter un minimum sur les générateurs de nombres aléatoires avant de prendre position sur ce sujet.
    J'ai peur que vous défendiez ce tutoriel pour de mauvaises raisons.
    J'espère sincèrement que la rédaction, dont vous faites partie, prendra rapidement en compte les remarques de eilijah et Jean-Marc.Bourguet pour le faire corriger.

  20. #20
    Invité
    Invité(e)
    Par défaut
    Bonjour ssMatio,
    Je parlais effectivement de randomize() qui est utilisable sous Windows.
    srand() est naturellement plus portable, mais il semble nécessaire de l'appeler avec un nombre aléatoire, par exemple l'heure. D'où ma préférence pour randomize() dans l'environnement Windows.
    Dernière modification par Emmanuel Delahaye ; 14/09/2010 à 12h53.

Discussions similaires

  1. les nombres aléatoires en builder
    Par farid0031 dans le forum C++Builder
    Réponses: 5
    Dernier message: 20/11/2009, 20h56
  2. Réponses: 6
    Dernier message: 15/10/2009, 21h18
  3. Etude sur les nombres pseudo-aléatoires
    Par odsen.s dans le forum C
    Réponses: 14
    Dernier message: 21/05/2007, 00h09
  4. [débutant] problème avec les nombres aléatoires
    Par happylife925 dans le forum Débuter
    Réponses: 12
    Dernier message: 10/03/2006, 15h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo