Vous êtes sur la page 1sur 13

Les nombres alatoires en C

par Nicolas Joseph (home) (Blog)

Date de publication : 10 Octobre 2005

Au travers de ce tutoriel, je vais vous exposer diffrentes mthodes pour gnrer une suite de nombres pseudo-alatoires. La thorie peut s'appliquer tous les langages de programmation. Par contre les exemples seront donns en C.

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

I - Introduction II - Les fonctions du C II-A - rand II-B - srand III - Une mthode (trop) simple IV - Mettons-y notre grain de sable V - Fixons des limites VI - Jouons la loterie VII - Comment calculer le hasard VIII - Conclusion IX - Remerciements

-2Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

I - Introduction
Pour commencer, je tiens rectifier le titre de ce tutoriel. En effet avec un ordinateur il est impossible de gnrer une suite de nombres rellement alatoires, nous devrons nous contenter de nombres pseudo-alatoires. Je vais donc vous proposer plusieurs mthodes, de la plus simple la plus complique, pour obtenir une srie de nombres difficilement dterminable l'avance (dite plus communment alatoire).

-3Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

II - Les fonctions du C
Avant de nous lancer dans la pratique, voici une brve description des fonctions permettant d'obtenir un nombre pseudo-alatoire en C. Ces fonctions sont dclares dans stdlib.h.

II-A - rand
Prototype :
int rand(void);

C'est cette fonction qui retourne un nombre alatoire chaque appel. Ce nombre est compris entre 0 et RAND_MAX.

II-B - srand
Prototype :
void srand(unsigned int seed);

La fonction srand permet d'initialiser le gnrateur de nombres pseudo-alatoires avec une graine diffrente (1 par dfaut). Elle ne doit tre appele qu'une seule fois avant tout appel rand.

-4Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

III - Une mthode (trop) simple


Voici une premire mthode :
int number = rand();

Je vous avais prvenu! Voici un exemple tout simple pour tester nos diffrentes mthodes :
#include <stdlib.h> #include <stdio.h> #include <time.h> int my_rand (void); int main (void) { int i; for (i = 0; i<1000; i++) { printf ("%d\n", my_rand()); } return (EXIT_SUCCESS); } int my_rand (void) { return (rand ()); }

A partir de maintenant, seule my_rand sera donne puisque le reste du programme sera le mme. Relancez le programme plusieurs fois et observez la suite de valeurs : elle est identique chaque appel ! Ceci est d la graine qui est toujours la mme : mme graine, mme suite de nombres ! On rservera donc cette mthode lorsque l'on a besoin d'un tableau d'entiers, pour viter d'avoir le remplir la main.

-5Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

IV - Mettons-y notre grain de sable


Vous l'aurez sans doute devin, pour viter de retrouver la mme suite de nombres chaque excution du programme, il faut modifier la graine, et donc appeler srand chaque dmarrage du programme avec une graine diffrente. Il y a une valeur qui est diffrente chaque appel du programme : l'heure. En initialisant le gnrateur avec l'heure actuelle, on devrait obtenir une suite de nombres diffrente chaque fois :
int my_rand (void) { static int first = 0; if (first == 0) { srand (time (NULL)); first = 1; } return (rand ()); }

La liste change chaque appel condition que intervalle de temps entre deux appels ne soit pas trop court (plus d'une seconde), sinon la suite de nombre sera la mme puisque la valeur retourne par time sera la mme.

-6Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

V - Fixons des limites


Jusqu' prsent, les valeurs obtenues sont comprises entre 0 et RAND_MAX. Il serait intressant de limiter l'intervalle de valeurs de 0 N-1. Pour commencer, une mthode simple consiste utiliser l'oprateur modulo (extrait de la FAQ C) :
#include <stdlib.h> int randomValue; randomValue = rand() % N;

Cette mthode ne fournit pas une distribution homogne des donnes (sauf si N est un multiple de RAND_MAX). En effet prenons l'exemple o N est gal 10 et RAND_MAX 25 : N randomValue [0;10[ [0;10[ [10;20[ [0;10[ [20;25[ [0;5[ Nous obtenons plus de nombres compris entre 0 et 5, pour pallier ce problme, il faut raliser une "mise l'chelle" (extrait de la FAQ C) :
#include <stdlib.h> int randomValue = (int)(rand() / (double)RAND_MAX * (N - 1));

-7Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

VI - Jouons la loterie
Pour ajouter une dose de hasard notre gnrateur va, lors du premier appel, crer un tableau de nombres alatoires, puis chaque nouvel appel un nombre sera pris au hasard dans ce tableau, sauvegard pour tre retourn par la fonction et pour finir remplacez par un nouveau nombre alatoire : il s'agit de l'algorithme de C. Bays et S.D.Durham.
#define N 100 int my_rand (void) { static int tab[N]; static int first = 0; int index; int rn; if (first == 0) { int i; srand (time (NULL)); for (i = 0; i < N; i++) tab[i] = rand(); first = 1; } index = (int)(rand() / RAND_MAX * (N - 1)); rn = tab[index]; tab[index] = rand(); return (rn); }

Maintenant que nous savons utiliser correctement un gnrateur de nombres alatoires, nous allons crer le ntre.

-8Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

VII - Comment calculer le hasard


Le titre de ce chapitre reflte bien le problme pos par la gnration de nombres alatoires : comment faire du hasard avec une machine aussi prcise qu'un ordinateur ? Au niveau matriel ne cherchez pas : tout est bas sur l'horloge interne, donc rgl comme du papier musique! Nous allons donc tre obligs de crer notre gnrateur. Comment ? En ralisant diffrentes oprations sur un nombre de dpart (appel graine ou seed en anglais) en suivant le principe des suites (rappelez vous vos cours de mathmatiques). D'autres se sont pos la question avant nous et en 1948, un certain Monsieur Lehmer a invent une formule gnrale de gnrateur : Xn+1 = ( a * xn + b ) % c L'oprateur % (modulo) renvoie le reste de la division entire de ses deux oprandes.

Voil, nous allons pouvoir recrer les fonctions srand et rand du C ! rand.h
#ifndef H_RAND #define H_RAND #include <limits.h> #define RAND_MAX INT_MAX void rnd_srand (unsigned int); int rnd_rand (void); #endif /* not H_RAND */

rand.c
#include "rand.h" static int g_seed = 1; void rnd_srand (unsigned int seed) { g_seed = seed; return; } int rnd_rand (void) { g_seed = ( 32 * g_seed + 7 ) % 1024; return (g_seed); }

Testons :
455 231 231 231 231 ...

C'est plutt prvisible pour une suite de nombres alatoires ! Un sujet aussi complexe que le hasard ne peut tre rsum par une formule aussi simple. Il existe des contraintes dans le choix des diffrents paramtres pour viter ce genre de problme (ce qui, ici, se dtecte facilement mais est parfois plus difficilement dcelable car visible uniquement pour des valeurs prcises de X) :
-9Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

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

Mme si ces conditions sont runies, il peut subsister des erreurs, ou plutt des imperfections au niveau du caractre alatoire 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 mme pour le gnrateur UNIX : Xn+1 = ( 1103515245 * xn + 12345 ) % 2147483647 Mme si ce gnrateur fonctionne correctement, il faut tout de mme faire attention : les octets de poids faibles ne sont pas rellement alatoires.

- 10 Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

VIII - Conclusion
Ce tutoriel vous a prsent les bases de la gnration de nombres pseudo-alatoires. Mais, bien sr, il existe un nombre bien plus important de gnrateurs. Vous pourrez en apprendre plus sur le forum algorithmes de developpez.com.

- 11 Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

IX - Remerciements
Merci 2Eurocents pour la relecture attentive de cet article.

- 12 Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/

Les nombres alatoires en C par Nicolas Joseph (home) (Blog)

- 13 Les sources prsents sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2005-2007 - Nicolas Joseph. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://nicolasj.developpez.com/articles/libc/hasard/