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

Bibliothèque standard C Discussion :

seed srand plus précis que time(NULL)


Sujet :

Bibliothèque standard C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut seed srand plus précis que time(NULL)
    Bonjour à tous,

    Après environ 3 heures de recherche je sèche...
    je cherche un seed pour srand qui soit plus précis que time, en effet en initialisant srand sur time(NULL) on obtient un seed identique sur 1 seconde complète.
    Hors je travaille actuellement sur un programme qui utilise des chaines de données aléatoires qui lui sont données par un programme externe.
    C'est ce dernier qui doit initialiser srand, mais il est appelé plusieurs fois par seconde!!! Donc je me retrouve avec les mêmes chaines lorsque les exécutions se font sur la même seconde.

    J'ai trouvé une solution temporaire en utilisant GetTickCount qui me permet de faire tourner le programme pour moi, mais je cherche une solution portable, ce qui n'est pas le cas de GetTickCount qui ne tourne que sur windows!

    Afin de ne pas perdre de temps inutilement, les réponses à quelques questions habituelles:
    - Mon srand se situe juste après le main, il n'est pas dans une boucle.
    - Il est absolument nécessaire d'avoir un seed plus précis qu'une seconde.
    - Je cherche une solution portable.
    - Je sais que l'intégration du programme externe dans le programme appelant résoudrait ce problème par la présence d'un seul srand. Mais il est indispensable de garder les 2 programmes séparés car il y a de nombreux programmes appelant différents.

    Je vous remercie d'avoir lu mon post et espère avoir des réponses constructives

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    J'ai eu le même problème i ly a quelque temps, j'avais pu me débrouiller avec time; en gros ça donnait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    time_t seed;
    size_t count;
     
    seed = time(NULL)
    while(seed == time(NULL)){
       ++count;
    }
     
    srand(seed + count);
    En gros, tant que la seconde pendnt laquelle time a été appelé la première fois n'est pas écoulée, on incrémente un compteur.
    Quand elle est finie, on initialise rand avec le temps de référence et le compteur.

  3. #3
    Membre émérite Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Par défaut
    Je ne m'y connais pas dans ce domaine, mais j'ai vu qu'il existait des devices capables de générer des nombres aléatoires (il y a des drivers pour de tels devices dans le noyau Linux).

    Si quelqu'un a déjà utilisé ces trucs !?

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    Tout d'abord merci de vos réponses rapides .

    mabu,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    seed = time(NULL)
    while(seed == time(NULL)){
       ++count;
    }
    Ca revient à attendre que la seconde soit écoulée si j'ai bien compris.
    Dans ce cas je m'interroge sur l'utilité du count, en réinitialisant srand sur time(null) on aura une graine différente puisque la seconde aura changée.

    Bref le problème est que cette solution oblige le programme à attendre 1 seconde, or le programme appelant peux atteindre dans certains cas plus de 10 requêtes par secondes. Ca ralentirais de manière significative le temps d'exécution!

    valefor
    Oui en effet, linux dispose de générateurs aléatoires plus performant que rand(). Mais par définition il ne seront pas portable.

  5. #5
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par Maniack Crudelis Voir le message
    Ca revient à attendre que la seconde soit écoulée si j'ai bien compris.
    Dans ce cas je m'interroge sur l'utilité du count, en réinitialisant srand sur time(null) on aura une graine différente puisque la seconde aura changée.
    *Le count est justement là pour ajouter de l'aléatoire.
    Imaginons (dans un environement multithread) que le programme soit appelé deux fois dans la même seconde, les deux appels sont séparés d'un dixième de seconde.

    0" 15 : premier appel du programme, il comment à compter.
    0" 25 : second appel du programme, il comment à compter.
    1" : la seconde est finie pour les deux programmes, en même temps, il vont appeler srand, mais puisque le premier appel a attendu plus longtemps, la constant d'init sera plus grande.

    Bref le problème est que cette solution oblige le programme à attendre 1 seconde, or le programme appelant peux atteindre dans certains cas plus de 10 requêtes par secondes. Ca ralentirais de manière significative le temps d'exécution!
    Le temps d'attente variera en gros de 0 à 1 seconde.

    Dans ton cas, on peut aussi imaginer une autre méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    srand(time(NULL) + getpid());
    Le getpid n'est pas à proprement portable tel quel, mais à l'aide de #define bien placés, on peut se débrouiller.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifdef WIN32
    GET_PID = GetCurrentProcessId
    #else //linux
    GET_PID = getpid
    #endif
    /* ... */
     
    srand(time(NULL) + GET_PID());

  6. #6
    Membre émérite Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Par défaut
    Citation Envoyé par Maniack Crudelis Voir le message
    valefor
    Oui en effet, linux dispose de générateurs aléatoires plus performant que rand(). Mais par définition il ne seront pas portable.
    Ben si c'est un périphérique, il suffit d'avoir un driver pour ta plateforme !

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Ne suffit-il pas, sous les systèmes POSIX, de lire quelques octets du "fichier" /dev/random ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    mabu
    Effectivement vu comme ça le count trouve tout son intérêt, je n'avais pas envisagé le problème sous cet angle, mais dans mon cas l'appel est toujours séquentiel.

    J'ai testé une initialisation du srand avec le PID, ça fonctionne effectivement. Au moment du test environ 5 exécutions à la seconde. Les tirages sont différents d'une exécution à l'autre.
    Donc c'est une solution tout à fait viable. D'autant plus que j'imagine que tout système octroie un PID à chaque programme s'exécutant.

    Cette solution va, pour le moment, équiper l'ensemble des programmes. Mais je reste ouvert à une solution complètement portable.
    Merci mabu pour cette solution

    Médinoc
    /dev/random... c'est pas portable ça et c'est une des contraintes principales

  9. #9
    Expert confirmé

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

    Tu peux utiliser la valeur renvoyée par QueryPerformanceCounter (Windows, je ne connais pas l'équivalent pour Linux, mais ça existe certainement).

    La valeur renvoyée change à chaque cycle horloge du processeur.

    Si tu veux le faire en assembleur, ça correspond en fait à ce que donne l'instruction rdtsc du processeur.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    QueryPerformanceCounter à l'avantage d'être beaucoup plus variable que le PID, mais mon application est un lanceur de dés donc c'est d'une incidence négligeable.
    Quoi qu'il en soit, ce qui importe à présent, le PID faisant son office, c'est que la solution soit complètement portable. Or en la matière QueryPerformanceCounter l'est tout autant que GetCurrentProcessId.

    J'ai souvenir d'une fonction se basant sur le proc et utilisée pour srand, mais qui se limitait au architecture x86, n'est-ce pas celle-ci?

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Attention aux idées reçues à propos de QueryPerformanceCounter() :
    QueryPerformanceCounter is not a source for unique identifiers
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    et en utilisant clock() ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    srand ( time(NULL)+clock() )
    pu quelque chose comme ça ??

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    Citation Envoyé par souviron34
    et en utilisant clock() ?
    Non, clock donne le temps depuis le démarrage de l'application, il donne donc en principe toujours le même temps jusqu'au srand. Et je l'affirme pour l'avoir justement testé!

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Maniack Crudelis Voir le message
    Non, clock donne le temps depuis le démarrage de l'application, il donne donc en principe toujours le même temps jusqu'au srand. Et je l'affirme pour l'avoir justement testé!
    clock est en CLOCKS_PER_SEC, dont la définition est bien inférieure à la seconde....

    En faisant un start=clock() au démarrage du programme, et ensuite un clock()-start

    et en ajoutant à time, on devrait avoir un id de l'ordre de la micro-seconde, non ??

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    seed = time(NULL) + (clock() - start)
    et même sans l'ajouter à time...

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    En faisant un start=clock() au démarrage du programme, et ensuite un clock()-start

    et en ajoutant à time, on devrait avoir un id de l'ordre de la micro-seconde, non ??
    Ton idée m'as parue intéressante, donc je l'ai testée, il apparait ce que je prévoyait, le temps d'exécution entre start=clock() et srand reste toujours identique. Du coup la graine ne change que chaque seconde .

  16. #16
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    étrange, car clock() est théoriquement correct. As-tu afiché la valeur de clock ?

    Sinon, prend ma routine dans les sources C (GetClock temps réel en secondes et microsecondes (exemple 1.000099) http://c.developpez.com/sources/?pag...DATE_get_clock), ça marchera.. Tant que tu es à l'extérieur de l'écart mini...

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    J'ai affiché la valeur de clock, et effectivement elle est identique entre start=clock() et srand!

    J'ai tester ta fonction souviron34, hélas j'ai une erreur de compilation 'gettimeofday' undeclared. Mais gettimeofday n'est pas sensée être une fonction nunux!?

  18. #18
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    regarde dans les ifdef au début...

    Il faut mettre le bon flag de compil. Elle est faite pour toutes les plateformes..

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Par défaut
    Je ne suis guère habitué des define et ifdef que j'exploite très rarement.
    En l'occurrence _WIN32 est déjà défini, peut-être par mon IDE!
    Mais afin de m'en assurer, j'ai changer le define par une autre variable, non définie par defaut, et j'ai recompilé. Toujours la même erreur sur gettimeofday, précisement ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    double GetClock ( void )
    {
      double d=-1.0 ;
     
     
    #ifndef __linux
    #ifdef _WIN32
       struct timeval tval ;
       struct timezone *tz=(struct timezone *)NULL ;
     
       timerclear(&tval);
     
       if ( gettimeofday(&tval, tz) )     /*Erreur de compilation ici!*/
       {

  20. #20
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    dans mingw il y est...

    Je ne sais pas quel IDE tu utilises, et à ce compte-là les autres habitués (Médinoc ou Emmanuel par exemple) sous Windows devraient pouvoir t'éclairer sur le .h à inclure.

    Avec Mingw c'est dans sys/time.h

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. plus précis que clock()
    Par piotrr dans le forum Général Python
    Réponses: 3
    Dernier message: 03/03/2008, 12h11
  2. Plus précis que time() ?
    Par Invité dans le forum VBScript
    Réponses: 0
    Dernier message: 17/01/2008, 15h18
  3. Un timer plus précis que SDL_GetTicks()
    Par goof_22 dans le forum SDL
    Réponses: 1
    Dernier message: 29/10/2006, 19h34
  4. Plus précis que datetime
    Par rvzip64 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 19/01/2006, 16h12
  5. [Info]Plus précis que System.currentTimeMillis()
    Par SuperCed dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 10/06/2005, 14h07

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