Problème avec rand() en C

Fermé
balraux Messages postés 3 Date d'inscription mercredi 16 juillet 2008 Statut Membre Dernière intervention 19 juillet 2008 - 19 juil. 2008 à 12:42
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 - 19 juil. 2008 à 14:46
Bonjour tout le monde,alors voila ma question:

J'ai un petit programme basé autour de la fonction rand() qui simule en fait un lancer de n dés
et qui retourne le nombre d'essais nécessaires avant de tomber sur un lancer où tous les dés
valent 1.
Aucun problème tant qu'on ne depasse pas un lancer de 11 dés, à partir de 12 dés le prog
tourne sans fin...
Pourtant jusqu'à 11 dés tout semble indiquer que le programme fonctionne "tres" bien.
ex: pour 11 dés, on répete 1000 fois le programme et on tombe sur une valeur moyenne
de 6^11 essais nécessaires (soit environ 363 000 000), ce qui tend vers la probabilité
mathématique d'un tel évènement.
C'est le même constat pour 10 dés, 9 dés etc...
Mais pour 12 dés on devrait trouver selon le meme principe une moyenne de 6^12 essais
(environ 2 200 000 000). Or le programme tourne sans fin, j'ai balisé le code, mais il ne
plante nul part! C juste qu'il ne tombe jamais sur 12 dés tous égaux à 1.
J'ai laissé tourner le programme jusqu'à 100 milliards de lancés et toujours rien.
Bref ya un problème.
Je soupconne la réinitialisation de la graine par srand(time(NULL)) qui doit me répeter un motif
certes très long mais un motif quand meme.
Je crois que cette réinitialisation se base sur l'heure en secondes de 1970 à nos jours.
C'est peut etre un facteur limitant dans mon cas.

Je compte sur vous, merci.


Voici mon code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
# define NBRDE 10
# define REP 10


main()
{
int a,b,c,j,somme,moy;
float p,k;

long long i;

float t;

somme=0;

srand(time(NULL));
for(k=0;k<=REP-1;k++)
{
b=0;
i=0;
p=k/(REP-1);

printf("%.2f %% effectues\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",p*100);

while(b!=NBRDE)
{
i++;

b=0;
for(j=0;j<=NBRDE-1;j++)
{
a=(int)((double)rand() / ((double)RAND_MAX + 1) * 6);
//printf("\na=%d",a);
if(a==1)
{
b++;
}
}
//printf("\n");
}



//printf("\nnombre d essais=%I64u\n",i);
//printf("\a");

somme=somme+i;
moy=somme/REP;

}
printf("\n\nsomme=%d\n",somme);
printf("moy=%d\n",moy);

t=clock();
printf("temps de calcul: %.3f secondes\n",t/1000);

system("pause");
return 0;

}Configuration: Windows Vista
Internet Explorer 7.0

2 réponses

mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
19 juil. 2008 à 14:01
Pour tout savoir sur le fonctionnement de rand :
http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/rand.3.html

Pour l'histoire de la suite aléatoire je suis d'accord, et pour peu que le motif se répète de sorte à ce que tu n'aies jamais simultanément 12 fois le chiffre 1 est théoriquement possible mais ça me paraît louche comme explication.

Si effectivement la boucle ne prend fin que quand les 12 dés sont égaux à 1 tu risques d'attendre un sacré moment avant que ça arrive.

À noter qu'en boost (une librairie libre écrite en C++) il existe d'autres générateurs aléatoires. Chez moi (sous linux) le programme marche avec NBRDE égal à 10 mais pas 12.

Quelques corrections :
- rajoute "int" devant main (type de retour)
- remplace system("pause"); par getchar();
- supprime la variable c
- pour afficher le long long int c'est plutôt %lli
- les tirages se font entre 0 et 5 (et non entre 1 et 6)

Quelques conseils :
- indente ton code
- donne des noms de variables explicites
- au lieu d'arrêter tes boucles à <= REP - 1 tu peux tout simplement écrire < REP

Le programme corrigé :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#define NOMBRE_DES 6
#define NOMBRE_JEUX 10

int main(){
    int valeur_de,nb_des_1,j,somme,moyenne;
    float pct_effectue,idx_jeu;
    long long nb_essais;

    somme = 0;

    srand(time(NULL));
    for(idx_jeu = 0;idx_jeu < NOMBRE_JEUX;++idx_jeu){
        nb_des_1 = 0;
        nb_essais = 0;
        pct_effectue = 100*idx_jeu/(NOMBRE_JEUX-1);

        printf("%.2f %% effectues\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",pct_effectue);

        while(nb_des_1 != NOMBRE_DES){
            ++nb_essais;
            nb_des_1 = 0;
            for(j = 0;j < NOMBRE_DES ;++j){
                valeur_de=(int)((double)rand() / ((double)RAND_MAX) * 6) + 1;
                printf("%d",valeur_de);
                if(valeur_de == 1) ++nb_des_1;
            }
            printf("\n");
        }
        printf("\nnombre d'essais = %lli\n",nb_essais);

        somme = somme + nb_essais;
        moyenne = somme / NOMBRE_JEUX;

    }
    printf("\n\nsomme = %d\n",somme);
    printf("moyenne = %d\n",moyenne);

    printf("temps de calcul: %.3f secondes\n",((double) clock())/1000);
    getchar();
    return 0;
}
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
19 juil. 2008 à 14:46
Salut,

voir aussi Générer des nombres aléatoires efficacement avec rand
0