Vous êtes sur la page 1sur 3

FIT 2 [INF202] 2010/11 Gnie Informatique

Algorithmique et programmation II
Damien Berthet & Vincent Labatut
Universit Galatasaray

TP 5

gnrateur pseudo-alatoire

1 Mthode de Lehmer
Dans un grand nombre dapplications, on a besoin de pouvoir gnrer des nombres de faon alatoire : calcul statistique, simulation physique, jeux vido, cryptographie, etc. Mais, par dfinition, le fonctionnement dun ordinateur classique est dterministe : les mmes causes entranent toujours le mme rsultat. Cela signifie quil est absolument impossible de gnrer alatoirement un nombre avec un ordinateur (sauf si on utilise un matriel spcifique). Pour rsoudre ce problme, diffrentes mthodes ont t dveloppes pour simuler le hasard, et gnrer des nombres en essayant de reproduire le mieux possible les proprits dun tirage alatoire. Les algorithmes qui utilisent ces mthodes sont appels des gnrateurs pseudo-alatoires de nombres. Un gnrateur pseudo-alatoire permet de produire une squence de nombres contenus dans un intervalle donn, de manire ce que chaque nombre soit apparemment indpendant du prcdent (on ne peut pas facilement prvoir quel sera le prochain nombre de la squence). De plus, le gnrateur est dfini de manire ce que cette squence reproduise les proprits dune distribution de probabilits donne. La plupart des gnrateurs alatoires simulent une distribution uniforme, c'est--dire une distribution pour laquelle toutes les valeurs de lintervalle possdent la mme probabilit dapparition. Par exemple, pour un intervalle , chaque valeur aura une probabilit dtre tire au sort. Un gnrateur alatoire est gnralement construit partir dune suite mathmatique possdant certaines proprits. Dans ce TP, on sintresse la mthode du gnrateur congruentiel linaire, dveloppe par Derrick Lehmer en 1948. Elle utilise la suite suivante : La tche consistant dterminer les valeurs des paramtres , et sort du cadre de ce TP. Nous utiliserons les valeurs , et , qui fonctionnent relativement bien pour gnrer des valeurs dans . Le terme initial est appel la graine du gnrateur pseudo-alatoire. Pour une suite donne et des paramtres fixs, le fait dutiliser la mme graine produira toujours la mme squence de nombres. Cette proprit (parmi dautres) diffrencie un gnrateur pseudo-alatoire dun gnrateur alatoire.

2 Implmentation
Exercice 1
Crez la bibliothque alea (i.e. crez les fichiers ncessaires, en leur donnant des noms appropris). Dans cette bibliothque, dfinissez la fonction unsigned char genere_nombre_lehmer() qui calcule le terme suivant dans la suite dcrite ci-dessus, et
FIT 2 [INF202] 2010/11 Gnie Informatique TP 5 1/3

Algorithmique et programmation II

gnrateur pseudo-alatoire

renvoie sa valeur. Vous devez dfinir toutes les constantes/macros/variables ncessaires, en utilisant les classes de mmorisation appropries. On supposera que la graine vaut . Crez un fichier main.c qui contiendra la fonction main. Dans cette fonction main, ajoutez les instructions ncessaires pour tester genere_nombre_lehmer : effectuez appels de la fonction et affichez les valeurs obtenues. exemple : le test doit provoquer exactement laffichage suivant :
graine: 0 nombres: 187 206 249 252 151 138 149 120 243 198

Exercice 2
La graine est initialise de faon statique, et par consquent la fonction va produire exactement la mme squence de nombres chaque excution. Pour viter cela, il faut initialiser la graine dynamiquement. Le plus simple est dutiliser lheure actuelle : cette valeur sera diffrente chaque excution (car le temps scoule), et donc la squence sera diffrente chaque excution. La fonction time_t time(time_t* t) contenue dans la librairie standard time.h prend en paramtre ladresse dune variable de type time_t, et lui affecte la date et lheure actuelles exprimes en secondes. Le type time_t est aussi dfini dans time.h et permet de reprsenter des donnes temporelles. La fonction renvoie en cas derreur, et sinon elle renvoie la date et lheure actuelles exprimes en secondes (i.e. la mme valeur que celle place dans t). Dans la bibliothque alea, crivez une fonction unsigned char init_graine_lehmer() qui initialise la graine en utilisant la fonction time. Votre fonction doit aussi renvoyer la valeur de la graine par valeur. De plus, vous devez tester les ventuels cas derreurs (et cette remarque vaut pour toutes vos fonctions en gnral). Testez votre fonction depuis le main, en lappelant plusieurs fois et en affichant la valeur de la graine chaque fois. Testez ensuite son effet sur genere_nombre_lehmer : excutez plusieurs fois le test de cette fonction (dfini pour lexercice prcdent) et vous devriez obtenir nombres diffrents chaque nouvelle excution. exemple : pour excutions, le test doit provoquer un affichage du type :
genere_nombre_lehmer
graine: 211 nombres: 166 145 84 175 98 45 208 11 158 73 graine: 226 nombres: 173 80 139 30 201 76 103 218 101 200 graine: 2 nombres: 205 112 171 62 233 108 135 250 133 232

Exercice 3
On veut gnrer n nombre entiers et les placer dans un tableau de dimension approprie. Dans alea, crivez une fonction unsigned char* genere_tableau_lehmer(int n) qui alloue dynamiquement la mmoire ncessaire, initialise le tableau alatoirement et renvoie son adresse. Testez cette fonction dans le main et affichez le contenu du tableau obtenu. exemple : pour , le test doit provoquer un affichage du type :
graine: 23 nombres: [ 10 21 248 115 70 49 244 79 2 205 112 171 62 233 108 ]

3 Vrification
Exercice 4
On veut vrifier que les nombres gnrs suivent bien une distribution uniforme. Pour cela, on peut calculer la moyenne, lcart-type et les valeurs minimales et maximales gnres. Les valeurs attendues pour cette distribution sont respectivement ; et . ;

Algorithmique et programmation II

FIT 2 [INF202] 2010/11 Gnie Informatique

TP 5 2/3

gnrateur pseudo-alatoire

Dans alea, crivez une fonction calcule_stats qui calcule et renvoie ces statistiques pour un tableau pass en paramtre. A vous de dterminer les paramtres appropris, sachant quaucun affichage ne doit tre ralis dans cette fonction. Testez votre fonction depuis le main, en affichant ces statistiques pour des tableaux de tailles , , , et . Que remarquez-vous ? exemple : le test doit provoquer un affichage du type suivant (attention : vous devez respecter cette mise en forme) :
graine: 157 n= 10: min= 56, max=192, moy=131.10, et=53.02 n= 100: min= 2, max=255, moy=117.18, et=77.46 n= 1000: min= 0, max=255, moy=127.08, et=73.64 n= 10000: min= 0, max=255, moy=127.54, et=73.92 n=100000: min= 0, max=255, moy=127.51, et=73.90

Remarque : pour calculer lcart-type, vous aurez besoin des fonctions pow(x,y) et contenues dans math.h, qui permettent respectivement de calculer et . Pour utiliser cette bibliothque sous Linux, il est ncessaire de configurer le linker en allant dans les proprits du projet, puis C/C++ Build > Settings > Tool Settings > gcc C linker > Libraries, puis dans longlet Libraries (-l) ajoutez la librairie m.
sqrt(x)

Exercice 5
Ces statistiques ne permettent toutefois pas de caractriser compltement la distribution des valeurs gnres. Pour plus de prcision, on peut lafficher directement sous la forme dun histogramme. Dans alea, crivez une fonction void calcule_repartition qui reoit un tableau et calcule la distribution des valeurs quil contient. Cette distribution doit prendre la forme dun tableau dist de taille , dont llment dist[i] contient le nombre doccurrences de la valeur i. Ainsi, dist[58] contient le nombre dapparitions de la valeur 58 dans le tableau gnr. Vous devez dcider des paramtres ncessaires votre fonction, sachant quelle doit allouer dist dynamiquement et quelle ne renvoie rien par return. Testez votre fonction depuis le main en gnrant un tableau de taille puis en affichant le contenu de dist et en vrifiant manuellement que les occurrences correspondent. exemple :
nombres: [ 105 236 7 122 4 104 99 182 33 100 ] dist: d( 0)= 0 d( 1)= 0 d( 2)= 0 d( 3)= d( 8)= 0 d( 9)= 0 d( 10)= 0 d( 11)= ...... 0 0 d( 4)= d( 12)= 1 0 ........ ........

Exercice 6
Dans alea, crivez une fonction void affiche_histogramme(int *dist) qui reoit en paramtre un tableau calcul laide de la fonction calcule_repartition, et laffiche sous la forme dun histogramme horizontal. Testez votre fonction depuis le main sur un tableau de nombres. La distribution est-elle uniforme ? exemple :
graine: 105 0 | *************************************** 1 | *************************************** 2 | *************************************** 3 | *************************************** .......

Algorithmique et programmation II

FIT 2 [INF202] 2010/11 Gnie Informatique

TP 5 3/3