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 :

Fonction rand() : séquence aléatoire trop courte ?


Sujet :

C

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 51
    Par défaut Fonction rand() : séquence aléatoire trop courte ?
    Bonjour,


    j'ai cherché solution à mon problème, mais je ne trouve rien !
    Je dois placer dans un tableau des pions au hasard. Je peux placer "x" pions par case.
    Je fais donc un petit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for (nbpions = 1000; nbpions >0;nbpions--) {
     
      int randi = rand() % i;
      int randj = rand() % j;
      if (tab[randi][rabdj] < nb_max)
         tab[randi][randj]++;
      else
         nbpions++;
    }

    J'espère donc que des pions vont se placer aléatoirement dans ma grille. La capacité de pion dans ma grille est bcp + grande que mon nombre de pion à placer.
    Malheureusement, à partir d'un moment, ma boucle se bloque dans le else. J'ai donc l'impression que le rand() me ressort une trop petite séquence de nombre qui se répète. Si je diminue le nombre de pion à placer à 100, mon programme se termine et marche très bien. Mais pour des nombre trop grand, ca cale ..


    Une solution pour régler mon problème please !

  2. #2
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 963
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 963
    Par défaut
    Jai,

    Combien peuvent valoir i, j et nb_max ?

    Tu peux savoir quelle sont les valeurs que rand peut renvoyer : de 0 à RAND_MAX (ou MAX_RAND, j'oublie chaque fois ), un test rapidement fait te donnera cette valeur.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 51
    Par défaut
    Comme j'ai dis, la capacité de mon tableau est plus grande que le nombre de pions à placer.
    Donc par exemple, i=50, j=50 et nbmax = 6
    On a donc une capacité de 15 000 pions. Et j'essaye d'en placer 1000.

    Je suis conscient que si j'essaye de placer, par exemple, 10000 pions pour une capacité de 9990 pions, ma fonction risque de tourner longtemps avant de trouver une place pour tout le monde

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Sachant que ton tableau peut contenir au maximum 50*50*6 pions (=15000), si ta boucle tourne sans fin (ie que ton tableau ne peut plus rajouter de pions), c'est que le tableau n'est pas correctement initialisé. Ses 50*50 éléments doivent tous être initialisés par des 0.

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 51
    Par défaut
    Ils le sont ..

    Donc je répète : Avec, par exemple, 100 pions à placer, aucun problème ! Mais dés que je veux mettre trop de pion, il boucle infiniment après un certain certain. J'ai donc l'impression que les rand() me sortent toujours les même séquences et que ces séquences sont trop courtes.

  6. #6
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Tu es sous quel OS ? Sur certains systèmes, les bits de poids faible retournés par rand() sont beaucoup moins aléatoires que les bits de poids fort. D'une manière générale, à parti si ton implémentation de rand() précise que ce n'est pas le cas, il faut éviter de faire un modulo pour normaliser les nombres dans l'intervalle voulu. Il vaut mieux faire une division.

    Cela dit ton algo de placement est assez naïf ; tu pourrais trouver un moyen de ne t'assurer que tu ne tireras plus jamais de valeurs qui ne sont plus acceptables (je te laisse chercher comment).

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 51
    Par défaut
    Sous linux.

    Pour faire un rand() dans un intervalle voulu, je n'ai trouvé que des astuces avec des modulo ..

    Et oui, mon algo est un peu naïf mais c'est un peu le rush là ... Et cette histoire n'est qu'une infime partie de ce que je dois faire .. C'est vraiment une bêtise qui me bloque et me fait perdre beaucoup de temps pour pas grand chose :p
    Si tu pouvais au moins me diriger vers de la documentation pour créer un algo de ce type ca m'intéresserait parce que je commence à être short niveau temps que pour "perdre" encore du temps sur ce rand() qui ne fonctionne pas comme je le voudrais :p


    Merci en tout cas pour ta réponse !

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Ils le sont ..
    Pour diagnostiquer un problème, on peut procéder par élimination. Il faut déjà s'assurer de certaines choses.

    Juste avant ton code, rajoute cela (le temps d'un test) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    {
    	int a,b,compt=0;
    	for (a=0; a<50; a++)
    	{
    		for (b=0; b<50; b++)
    		{
    			compt += (tab[a][b]==0);
    		}
    	}
    	printf("%d\n",compt);
    }
    ... et dis-moi si la valeur affichée est bien 2500.

    Si c'est le cas, alors le problème peut éventuellement venir de rand.

  9. #9
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Ce programme doit tourner rapidement, SAUF si tu demandes plus de i*j*nb_max (soit 15000 dans l'exemple) pions. Dans ce cas, il tourne indéfiniment puisqu'il n'a pas la possibilité de mettre les derniers.

  10. #10
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Citation Envoyé par sikin1989 Voir le message
    Si tu pouvais au moins me diriger vers de la documentation pour créer un algo de ce type ca m'intéresserait parce que je commence à être short niveau temps que pour "perdre" encore du temps sur ce rand() qui ne fonctionne pas comme je le voudrais :p
    Tu peux allouer un tableau T de N = i*j pointeurs qui te servira à tirer des cases. Tu l'initialises de façon à ce que chaque case pointe vers une case de ta grille. Tu tires un nombre n entre 0 et N-1, et tu vas incrémenter *T[n] (qui est une case de ta grille). Si la nouvelle valeur est nb_max, tu échanges les cases T[N-1] et T[n] (tu fais passer la case que tu ne veux plus tirer en fin de tableau), et tu décrémente N de 1 de façon à ne plus tirer la case que tu viens d'éliminer.

    Ca évite de faire des rand() qui ne servent à rien. Evidemment c'est surtout intéressant quand tu as beaucoup de pions à placer par rapport à i*j*nb_max.

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @matafan
    Evidemment c'est surtout intéressant quand tu as beaucoup de pions à placer par rapport à i*j*nb_max.
    Il ne peut pas placer plus de i*j*nb_max pions.

  12. #12
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par sikin1989 Voir le message
    Pour faire un rand() dans un intervalle voulu, je n'ai trouvé que des astuces avec des modulo ..

    Je te renvoie à la FAQ : Comment obtenir un nombre aléatoire (entier) entre 0 et N ?

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 51
    Par défaut
    Citation Envoyé par diogene Voir le message
    @matafan

    Il ne peut pas placer plus de i*j*nb_max pions.
    Il voulait sûrement dire que c'est intéressant lorsque le nombre de pion à placé s'approche de i*j*nb_max

    J'avais pensé à faire ça mais bon .. je trouvais ça trop peu efficace pour le nombre de fois où je vais m'en servir. Le nombre totale de pion à placer n'approchera pas souvent (même peut être jamais) la capacité totale de ma grille. Je vais donc garder mon algo en tentant de le faire marcher.

    @jeroman : Oui, ca fait bien 2500 itérations

    @gl : Merci, j'avais pas trouvé

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    C'est vraiment étonnant que rand renvoie les mêmes séries.

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    5
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 5
    Par défaut
    Citation Envoyé par sikin1989 Voir le message
    Bonjour,


    j'ai cherché solution à mon problème, mais je ne trouve rien !
    Je dois placer dans un tableau des pions au hasard. Je peux placer "x" pions par case.
    Je fais donc un petit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for (nbpions = 1000; nbpions >0;nbpions--) {
     
      int randi = rand() % i;
      int randj = rand() % j;
      if (tab[randi][rabdj] < nb_max)
         tab[randi][randj]++;
      else
         nbpions++;
    }

    J'espère donc que des pions vont se placer aléatoirement dans ma grille. La capacité de pion dans ma grille est bcp + grande que mon nombre de pion à placer.
    Malheureusement, à partir d'un moment, ma boucle se bloque dans le else. J'ai donc l'impression que le rand() me ressort une trop petite séquence de nombre qui se répète. Si je diminue le nombre de pion à placer à 100, mon programme se termine et marche très bien. Mais pour des nombre trop grand, ca cale ..


    Une solution pour régler mon problème please !
    Il y a la fonction int random() de la stdlib bien plus aléatoire. Elle est fournie avec int RAND_MAX

  16. #16
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par kruller Voir le message
    Il y a la fonction int random() de la stdlib bien plus aléatoire. Elle est fournie avec int RAND_MAX
    Attention, la fonction random() n'est pas une fonction standard (c'est du BSD d'après la page man).

    Et au passage, rand() fournie déjà un nombre entre 0 et RAND_MAX.

  17. #17
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    - @jeroman
    C'est vraiment étonnant que rand renvoie les mêmes séries.
    je ne crois pas non plus que la fonction rand() fournie avec un compilateur puisse être si mauvaise qu'elle ne puisse remplir les 50*50*6 = 15000 pions.

    - le biais introduit par l'utilisation des modulos avec des valeurs de i et j aussi faibles (50) doit être négligeable (pour un RAND_MAX supérieur ou égal à 32767)

    - même si on veut mettre 15000 pions, le remplissage sera rapide : pour donner une idée, si on a déjà placé 14999 pions, il reste une seule case possible pour le 15000 ième. A chaque boucle, on sélectionne une case du tableau et on a une probabilité de 1/2500 de toucher la case disponible et de terminer au premier essai. On a 50% chances de la remplir en moins de 1700 essais , 80% en moins de 4000, 90% en moins de 6000 et 98% en moins de 10000. Ce ne sont pas des chiffres gigantesques sur une machine moderne.

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/03/2014, 14h27
  2. fonction rand() php
    Par taka10 dans le forum Langage
    Réponses: 5
    Dernier message: 12/04/2006, 13h35
  3. [VB]Winsock - Variable trop courte ?
    Par Benji Le Magic dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 27/01/2006, 15h23
  4. [vba-excel] Le temps de fermeture trop court ?
    Par Damsou dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 11/01/2005, 10h03
  5. [LINUX][INSTALL]Error de fichier trop court
    Par silvermoon dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 06/08/2004, 16h17

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