Random bizarre

CrazyJoCrazyJo Membre
20:58 modifié dans API AppKit #1
J'ai mis cette ligne de code  pour tirer un chiffre au hasard entre 1 et 3 ( 1 et 3 compris) :
int randomNumber = (random() % 3) + 1;

Ce qui est bizarre c'est que le premier chiffre tiré au hasard est toujours le même. Tout le temps c'est le chiffre 1 qui est sorti en premier ! Comment remédier à  ce problème ?
---autre petite chose peut-on mettre ce code en une seul ligne seulement  ? :
[infoGame setStringValue:@&quot;You&#39;ve lost&quot;];<br />[infoGame setTextColor:[NSColor redColor]];


merci o:)

Réponses

  • Philippe49Philippe49 Membre
    20:58 modifié #2

    C'est du C : si on n'utilise pas  srandom() avant random(), la liste des nombres tirés par random() est toujours la même

    On fait précéder par srandom(time(NULL)); pour initialiser le hasard via la date machine.
    tu trouveras  pléthore d'explication sur Internet
  • CrazyJoCrazyJo Membre
    20:58 modifié #3
    dans 1187434876:


    C'est du C : si on n'utilise pas  srandom() avant random(), la liste des nombres tirés par random() est toujours la même

    On fait précéder par srandom(time(NULL)); pour initialiser le hasard via la date machine.
    tu trouveras  pléthore d'explication sur Internet

    ah ok je l'avais placé après ... ???
  • schlumschlum Membre
    20:58 modifié #4
    De toute manière, pour avoir de l'aléatoire un peu plus "sérieux", il vaut mieux aller lire le fichier /dev/random
  • AntilogAntilog Membre
    août 2007 modifié #5
    Cela dit, ça a un coté très pratique de pouvoir utiliser toujours la meme série de nombres (pseudo-)aléatoires, afin de tester. Pour cela, srandom(x) avec initialisation de x juste avant!
  • AntilogAntilog Membre
    20:58 modifié #6
    dans 1187439259:

    De toute manière, pour avoir de l'aléatoire un peu plus "sérieux", il vaut mieux aller lire le fichier /dev/random

    "La génération de nombre aléatoires est trop importante pour etre laissée au hasard..."
  • Philippe49Philippe49 Membre
    20:58 modifié #7
    dans 1187474572:

    "La génération de nombre aléatoires est trop importante pour etre laissée au hasard..."


    Cela me fait penser à  la disparition de Michel Serraut .. à  son lyrisme plein d'humour
  • AntilogAntilog Membre
    20:58 modifié #8
    dans 1187475519:

    dans 1187474572:

    "La génération de nombre aléatoires est trop importante pour etre laissée au hasard..."


    Cela me fait penser à  la disparition de Michel Serraut .. à  son lyrisme plein d'humour


    Pour moi, ça commence à  se rapprocher de la pataphysique!

    Pour rendre à  César, ...
    j'ai recherché l'auteur, il s'agit de Robert R. Coveyou du Oak Ridge National Laboratory (source Wikipédia http://fr.wikipedia.org/wiki/G%C3%A9n%C3%A9rateur_de_nombres_pseudo-al%C3%A9atoires)

  • CrazyJoCrazyJo Membre
    20:58 modifié #9
    Et je relance le sujet car j'ai un nouveau petit problème du même genre:
    srandom(time(NULL));											 <br />	int nombreAleatoire1 = (random() % [nb2 intValue ]) + [nb1 intValue ];								// On tire le premier chiffre au hasard entre nb1 et nb2 -&gt; règlable dans les préfs.<br />	NSLog(@&quot;nombreAleatoire1 est : %i&quot;,nombreAleatoire1);<br />	srandom(time(NULL));<br />	int nombreAleatoire2 = (random() % [nb2 intValue ]) +&nbsp; [nb1 intValue ];								// On tire le deuxième chiffre au hasard entre nb1 et nb2 -&gt; règlable dans les préfs.<br />	NSLog(@&quot;nombreAleatoire2 est : %i&quot;,nombreAleatoire2);<br />
    

    L'ordi tire des chiffres complètement à  coté de la plaque dès que l'on change nb1 ou/et nb2 (qui sont des TextField)


    A Schlum :  Je ne trouve pas ça : /dev/random  chez moi..
  • schlumschlum Membre
    20:58 modifié #10
    C'est parce que ton assertion est fausse...
    random()%nb2+nb1 n'est pas un nombre entre nb1 et nb2, mais un nombre entre nb1 et nb1+nb2-1

    Si tu veux un nombre entre nb1 et nb2, c'est (random()%(nb2-nb1+1))+nb1

    En plus, srandom(time(NULL)); doit être mis avant les appels à  "random"


    Si tu n'as pas /dev/random, c'est inquiétant... Tu es sous Windows ?  :)
    Nota : /dev est un répertoire invisible
  • Philippe49Philippe49 Membre
    20:58 modifié #11
    srandom() ne se met qu'une seule fois.


  • schlumschlum Membre
    20:58 modifié #12
    Oui, mais avant quand même  :P
  • Philippe49Philippe49 Membre
    20:58 modifié #13
    dans 1197740403:

    Oui, mais avant quand même  :P


    certes  ;D
  • fubu33fubu33 Membre
    20:58 modifié #14
    Pour générer un nombre aléatoire j'ai toujours procédé ainsi :

    <br />int nombre = 0;<br /><br />srand(time(NULL));<br /><br />nombre = hasard(0, 100);<br />
    


    où la fonction hasard() est implémentée ainsi :

    int hasard(int min, int max){<br />return (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));<br />}
    


    Comme ça on obtient un nombre entre 0 et 100, c'est peut-être pas la meilleure méthode mais elle fonctionne bien  :).
    ( je précise que la fonction hasard() n'est pas de moi, je l'ai trouvé sur un tuto ;) )

  • Philippe49Philippe49 Membre
    20:58 modifié #15
    dans 1197823525:


    Comme ça on obtient un nombre entre 0 et 100, c'est peut-être pas la meilleure méthode mais elle fonctionne bien  :).
    ( je précise que la fonction hasard() n'est pas de moi, je l'ai trouvé sur un tuto ;) )


    La page man de la fonction random() indique l'optimisation (selon l'auteur de cette page)
  • schlumschlum Membre
    décembre 2007 modifié #16
    Le random le plus fiable qui existe :

    unsigned long long rand()<br />{<br />  int fp = open(&quot;/dev/urandom&quot;,O_RDONLY,0);<br />  unsigned long long rand;<br />  read(fp,&amp;rand,sizeof(long long));<br />&nbsp; close(fp);<br />  return rand;<br />}
    


    (avec "#include <fcntl.h>")

    Par contre, si on a besoin de beaucoup de valeurs aléatoires, il vaut mieux lire directement un gros tableau dans /dev/urandom pour limiter les I/O.
  • Philippe49Philippe49 Membre
    décembre 2007 modifié #17
    random

    arc4random

    Tu as des sources sur la qualité de /dev/random ?

    Expérience
    #include <stdio.h>
    #include <stdlib.h> 
    #include <fcntl.h>
    #define N 10000
    #define M 10

    #define INITMYRAND fp=open("/dev/urandom",O_RDONLY,0)
    #define MYRAND (read(fp,& myrandrand,sizeof(long long)), myrandrand)
    int fp ;
    unsigned long long myrandrand;

    int main(void){
    int i,j,method;
    INITMYRAND;
    printf("   myrandom : arc4random :     random\n");
    for(j=1;j<M;j++){
    unsigned long long S1=0,S2=0,S3=0;
    for(i=0;i<N;i++){
    S1+=MYRAND %1024;
    S2+=arc4random()%1024;
    S3+=random()%1024;
            }
    printf(" %10.2f : %10.2f : %10.2f\n",(double)S1/N,(double)S2/N,(double)S3/N);
            }
            close(fp);
            return 0;
    }



    Résultat :
    % pgm
       myrandom : arc4random :     random
         508.41 :     510.34 :     508.99
         515.37 :     512.26 :     514.48
         512.49 :     507.75 :     508.59
         506.42 :     516.60 :     503.00
         517.13 :     514.41 :     516.24
         512.15 :     514.98 :     510.62
         509.06 :     511.41 :     507.85
         509.31 :     513.42 :     509.47
         515.36 :     511.57 :     507.88
    %

  • Philippe49Philippe49 Membre
    décembre 2007 modifié #18
    Ce qui est rigolo à  faire c'est
          cat  /dev/random > machin
    mais pas trop longtemps quand même, le Go est vite arrivé


    Citation
    Les fichiers spéciaux caractères /dev/random et /dev/urandom (existants depuis Linux 1.3.30) fournissent une interface avec le générateur de nombres aléatoires du noyau.
    Le fichier /dev/random a un numéro de périphérique majeur égal à  1, et un numéro mineur égal à  8. Les numéros du périphérique /dev/urandom sont 1 pour le majeur, et 9 pour le mineur.
    Le générateur de nombres aléatoires regroupe du bruit provenant de son environnement par l'intermédiaire des pilotes de périphériques et d'autres sources, et le stocke dans un réservoir d'entropie. Le générateur mémorise également une estimation du nombre de bits de bruit dans son réservoir d'entropie, et utilise son contenu pour créer des nombres aléatoires.
    Lors d'une lecture, le périphérique /dev/random sera limité au nombre de bits de bruit contenus dans le réservoir d'entropie.
    /dev/random est particulièrement adapté pour les cas où l'on a ponctuellement besoin de nombres hautement aléatoires (création de clés par exemple). Lorsque le réservoir d'entropie est vide, les lectures depuis le périphérique /dev/random seront bloquantes jusqu'à  l'obtention de suffisamment de bruit en provenance de l'environnement.
  • schlumschlum Membre
    décembre 2007 modifié #19
    "/dev/urandom" c'est pareil que "/dev/random", sauf qu'il ne bloquera jamais  ;)
    (par contre, moins d'entropie au bout d'un moment...)

    PS : j'ai édité au dessus, j'avais oublié le "close"... Gaffe à  ne jamais faire si on ne veut pas se retrouver avec un bug super désagréable et difficile à  trouver :)
  • Philippe49Philippe49 Membre
    20:58 modifié #20
    Le man BSD d'Apple recommande arc4random(), qui utilise /dev/urandom pour s'auto-initialiser.
    Cela me semble un bon compromis surement testé avec des outils spécialisés.
    Y a-t-il des tests de fiabilité sur /dev/(u)random ?
  • schlumschlum Membre
    20:58 modifié #21
    C'est ce qui se rapproche le plus d'un générateur aléatoire (dépend du bruit matériel), les autres étant des générateurs pseudo-aléatoires.
  • Philippe49Philippe49 Membre
    20:58 modifié #22
    dans 1197883869:

    (dépend du bruit matériel)


    Ca c'est pour vendre la lessive, mais derrière ?
  • schlumschlum Membre
    décembre 2007 modifié #23
    Bah derrière tu peux lire l'article de Wikipedia :
    http://en.wikipedia.org/wiki//dev/random

    Et si t'es motivé, ce document :
    http://www.pinkas.net/PAPERS/gpr06.pdf
  • schlumschlum Membre
    20:58 modifié #24
    Par exemple, il me semble que les mouvements de la souris, les actions sur le clavier, les I/O des disques etc... Contribuent à  l'entropie de /dev/random
Connectez-vous ou Inscrivez-vous pour répondre.