Nombre aléatoire

4 réponses
Avatar
ZarkXe
Bonjours à tous,

J'ai un petit problème qui me laisse perplexe ! Je veux générer un grand
nombre de nombre aléatoire ( Par exemple n fois) puis je le stock dans
un fichier. Et de réitérer l’expérience plusieurs fois.

> Voici le programme qui généré les nombres aléatoire :

#include <stdio.h>
#include <stdlib.h>
#include <time.h> //Ne pas oublier d'inclure le fichier time.h

int main(void){
int i = 0;
int nombre_aleatoire = 0;
srand(time(NULL)); // initialisation de rand
for(i=0; i<500; i++){
nombre_aleatoire = rand();
printf("%d\n",nombre_aleatoire);
}
return 0;
}

> Et voici le programme qui appel au générateur de nombre aléatoire
plusieurs fois (100fois) et socket les résultats dans un fichier
différant pour chaque expérience.

#!/bin/bash

for i in {1..100}
do
./random > experience-$i.csv
done

> Pour regarder si chaque expérience est différant, je fait un md5 de
chaque fichier qui contient les nombres aléatoire :
$ md5sum *
7f6ed5ee2ef611cbe913dad427b766d6 experience-100.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-10.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-11.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-12.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-13.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-14.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-15.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-16.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-17.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-18.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-19.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-1.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-20.csv
7f6ed5ee2ef611cbe913dad427b766d6 experience-21.csv
....

> Je ne comprend pas pourquoi j'ai la même chose dans chaque fichier
alors que je remplis chaque fichier avec n nombre aléatoire !

Merci d'avance.

ZarkXe

4 réponses

Avatar
Olivier Miakinen
Bonjour,

Le 13/10/2012 00:07, ZarkXe a écrit :

J'ai un petit problème qui me laisse perplexe ! Je veux générer un grand
nombre de nombre aléatoire ( Par exemple n fois) puis je le stock dans
un fichier. Et de réitérer l’expérience plusieurs fois.

[...]
srand(time(NULL)); // initialisation de rand
[...]

#!/bin/bash

for i in {1..100}
do
./random > experience-$i.csv
done

[...]

Je ne comprend pas pourquoi j'ai la même chose dans chaque fichier


alors que je remplis chaque fichier avec n nombre aléatoire !



Je parie que ça prend moins d'une seconde à créer les 100 fichiers.
Du coup tu initialises 100 fois srand() avec la même valeur, et il
est parfaitement normal que les 100 fichiers aient le même contenu.

Je ne connais pas ton besoin, mais une idée pourrait être que ton
programme stocke dans un fichier fixe sous /tmp la dernière valeur
de rand(), et que ce soit celle-ci qui soit utilisée comme graine
à l'appel suivant.

Cordialement,
--
Olivier Miakinen
Avatar
Samuel DEVULDER
Le 13/10/2012 00:07, ZarkXe a écrit :

...
srand(time(NULL)); // initialisation de rand
...
Je ne comprend pas pourquoi j'ai la même chose dans chaque fichier


alors que je remplis chaque fichier avec n nombre aléatoire !



Hypothèse: la génération des 100 fichiers se fait en moins d'1 sec. Du
coup time(NULL) retourne la même graine pour chacune des 100 exécutions.

Contournement: initialiser avec des micro-secondes (voit gettimeofday je
crois), ou un autre aléa (pid?). Attention avec les micro-secondes
(tv_usec), c'est une valeur modulo 1000000, donc toutes les secondes les
valeurs sont identiques. Il vaudrait mieux mélanger tous les champs de
la struct timeval pour augmenter l'entropie.

Il faut aussi savoir que le générateur de rand() n'est pas terrible. Il
vaudrait mieux passer par un générateur plus robuste tel random(3). A
mon sens l'idéal sous un POSIX est d'utiliser le fichier /dev/random
car il utilise une entropie globale au système. Si la lecture de ce
fichier est trop lente pour ton appli (/dev/random est blocant quand
l'entropie du système est trop faible), tu peux probablement te
contenter de l'utiliser comme graine au début de ton programme et
basculer ensuite sur le random(3) du C.

sam.
Avatar
ZarkXe
Merci à tous. Je comprend mieux le problème, cela vient principalement
de ma graine.

Le 10/13/2012 12:36 AM, Samuel DEVULDER a écrit :
Le 13/10/2012 00:07, ZarkXe a écrit :

...
srand(time(NULL)); // initialisation de rand
...
Je ne comprend pas pourquoi j'ai la même chose dans chaque fichier


alors que je remplis chaque fichier avec n nombre aléatoire !



Hypothèse: la génération des 100 fichiers se fait en moins d'1 sec. Du
coup time(NULL) retourne la même graine pour chacune des 100 exécutions.

Contournement: initialiser avec des micro-secondes (voit gettimeofday je
crois), ou un autre aléa (pid?). Attention avec les micro-secondes
(tv_usec), c'est une valeur modulo 1000000, donc toutes les secondes les
valeurs sont identiques. Il vaudrait mieux mélanger tous les champs de
la struct timeval pour augmenter l'entropie.

Il faut aussi savoir que le générateur de rand() n'est pas terrible. Il
vaudrait mieux passer par un générateur plus robuste tel random(3). A
mon sens l'idéal sous un POSIX est d'utiliser le fichier /dev/random car
il utilise une entropie globale au système. Si la lecture de ce fichier
est trop lente pour ton appli (/dev/random est blocant quand l'entropie
du système est trop faible), tu peux probablement te contenter de
l'utiliser comme graine au début de ton programme et basculer ensuite
sur le random(3) du C.

sam.
Avatar
erwan
Olivier Miakinen <om+ écrivait :

Bonjour,

Le 13/10/2012 00:07, ZarkXe a écrit :

J'ai un petit problème qui me laisse perplexe ! Je veux génà ©rer un grand
nombre de nombre aléatoire ( Par exemple n fois) puis je le stock d ans
un fichier. Et de réitérer l’expérience plusieurs fois.

[...]
srand(time(NULL)); // initialisation de rand
[...]

#!/bin/bash

for i in {1..100}
do
./random > experience-$i.csv
done

[...]

Je ne comprend pas pourquoi j'ai la même chose dans chaque fichier


alors que je remplis chaque fichier avec n nombre aléatoire !



Je parie que ça prend moins d'une seconde à créer les 100 fichiers.
Du coup tu initialises 100 fois srand() avec la même valeur, et il
est parfaitement normal que les 100 fichiers aient le même contenu.

Je ne connais pas ton besoin, mais une idée pourrait être que t on
programme stocke dans un fichier fixe sous /tmp la dernière valeur
de rand(), et que ce soit celle-ci qui soit utilisée comme graine
à l'appel suivant.

Cordialement,



Ou alors ajouter le PID du processus, ou tout simplement prendre ce qui
a été fait poru : lire dans /dev/random ou /dev/urandom


--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé