Rand() me renvoit une fois sur deux la même valeur

Rand() me renvoit une fois sur deux la même valeur - C++ - Programmation

Marsh Posté le 27-10-2011 à 00:31:28    

Bonsoir :hello:  
 
J'ai un sacré problème avec la fonction rand(), la valeur de retour est une sur deux sur la même, en gros le résultat ressemble à ça :  
12.485366374706
0.14142277291177
12.485366374706
0.14142277291177
12.485366374706
0.14142277291177
12.485366374706
0.14142277291177
12.485366374706
0.14142277291177
 
J'comprends vraiment pas, le rand() est bidon où j'm'en sert mal ? :heink:  
 
mes fonctions pour avoir un nombre aléatoire :
 

Code :
  1. float random(float l,float h)
  2. {
  3. return rand()/(float)(RAND_MAX) * (h-1)+l;
  4. }
  5. int irandom(int l,int h)
  6. {
  7. return rand()%(h-l+1) + l;
  8. }


 
Et lors de l'initialisation du programme, j'utilise srand(time(NULL)) pour le seed.
J'ai tenté avec la SFML d'utiliser sf::Randomizer, mais j'avais pas de bon résultats non plus :sisicaivrai:
 
Quelqu'un aurait une idée ? Le boost::random fonctionne mieux ?
 
Merci à vous et bonne soirée/nuit :D  


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 27-10-2011 à 00:31:28   

Reply

Marsh Posté le 27-10-2011 à 04:58:14    

On peut avoir le code source complet de ton truc ? :o


Message édité par WiiDS le 27-10-2011 à 05:04:01

---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 27-10-2011 à 18:37:49    

Oui m'sieur :D
 
C'est un code lua qui appelle la fonction :  
 

Code :
  1. function strike()
  2. local e;
  3. for i=0,get_map_width()/16 do
  4. local r = irandom(0,5);
  5.   if (r==0) then
  6.    e = create_event(i*16+random(-20,20),irandom(-600,-10),"Events/MON/Lavarock" );
  7.    perform_event_function(e,"always_explode" );
  8.   end
  9. end
  10. end


 
Donc le principe c'est tout bête, lorsque cette fonction est appelée, elle est supposée créé plein de bouboules qui tombe au hasard sur la carte (la fonction qui créé un objet s'appelle create_event(x,y,fichier_lua)
 
Donc en gros, ce code me permettait normalement d'avoir une chance sur 5 d'avoir une pierre qui tombe, mais le 'irandom(0,5)' me renvoyait certaine fois plein de '0', du coups j'avais une belle tombée de pierres bien alignée..
 
J'ai réussi à palier ça en recréant une seed à chaque pas de i, via randomize(i), qui appelle cette fonction c++ :  

Code :
  1. void randomize(unsigned int s)
  2. {
  3. srand(time(NULL)+s);
  4. }


 
Et à la fin de la boucle, un randomize(0) pour remettre à time(NULL), mais j'ai entendu dire que régénérer une seed, c'était pas cool.. Mais ça semble mieux fonctionner :D


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 27-10-2011 à 19:49:24    

Hmm. Théoriquement t'es pas censé exécuter srand plus d'une fois.
 
Après désolé mais je vois pas trop ce qui pourrait te causer problème dans ton cas :D


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 27-10-2011 à 20:24:40    

Je connais pas lua, mais si ça crée des threads avec create_event, alors dans chaque thread, les appels a rand vont générer la même séquence, donc il est logique que tu voies les mêmes valeurs.
Si tu veux des valeurs différentes pour chaque thread, lors des appels à rand, il faudrait seeder avec des valeurs différentes dans chaque thread (en utilisant le thread-id ou autre)
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 27-10-2011 à 21:54:59    

create_event est une fonction que j'ai faite, qui permet d'instancier une class c++ "EventClass"qui contient un lua_State, enregister celle-ci dans ma liste d'objet à traiter et elle renvoit son indentifier (sa "position" dans une std::map<int,EventClass*> ).
Mon programme n'utilise que 2 Threads : Un qui gère les packets en réseau (réception), un autre qui fait tout le reste (exécuter les fonctions lua qu'il faut, dessiner à l'écran, bref tout le bordel du moteur)
 
Donc normalement tout mon moteur n'utilise qu'une seul seed, celle qui est définie au début par "srand(time(NULL))", je m'y prend mal du coups?


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 27-10-2011 à 22:25:05    

Apparemment non, mais tout se passe comme si rand une fois appelée était déchargée de la mémoire et perdait son état (rand est une fonction qui doit avoir une variable statique quelque part, ce qui lui permet de ne pas renvoyer la même valeur à chaque appel).
Car rand est une fonction détermiste: pour une même valeur de seed, elle renvoie toujours la même suite de nombres aléatoires.
On dirait donc qu'a chaque fois, elle revoit la même seed, ou qu'elle voit pas sa variable de dernier état.
Si tu peux utiliser rand_r et faire exister la variable d'état dans ton code au lieu que ce soit une variable statique à la fonction rand, cela améliorera peut être les choses.
A+,


Message édité par gilou le 27-10-2011 à 22:34:35

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 28-10-2011 à 02:14:24    

Hm, rand_r() marchait pas chez moi, (undeclared alors que j'avais bien le #include<stdlibs> ) du coups j'ai choppé la fonction sur le net :

 
Code :
  1. int
  2.     rand_r (unsigned int *seed)
  3.     {
  4.       unsigned int next = *seed;
  5.       int result;
  6.       next *= 1103515245;
  7.       next += 12345;
  8.       result = (unsigned int) (next / 65536) % 2048;
  9.       next *= 1103515245;
  10.       next += 12345;
  11.       result <<= 10;
  12.       result ^= (unsigned int) (next / 65536) % 1024;
  13.       next *= 1103515245;
  14.       next += 12345;
  15.       result <<= 10;
  16.       result ^= (unsigned int) (next / 65536) % 1024;
  17.       *seed = next;
  18.       return result;
  19.     }
 

Et ça marche bien apparemment, merci :D

 

edit : Par contre je me demande, les diverses opérations appliqués à result et next sont faites au hasard, où y'a une logique à tout ça :??:

Message cité 1 fois
Message édité par Terminapor le 28-10-2011 à 02:19:54

---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 11-11-2011 à 23:18:47    

oui les papiers de recherche sont accessibles. il existe bcp d'autres fonctions de pseudo random. il est admis de nos jour que mersenne twister devrait etre utilisé de préférence. (eg defaut dans boost)
la fonction que tu utilises ci dessus est une variation du rand implémenté dans la libc. en tout cas tu as les memes nombres.
j'aurais dit que ca aurait pu ressembler a un rand taus (taus88) mais tu n'as pas 3 variables next differentes donc ca ne doit pas etre ca.


---------------
http://projets.6mablog.com/
Reply

Marsh Posté le 12-11-2011 à 10:54:56    

Terminapor a écrit :

Hm, rand_r() marchait pas chez moi, (undeclared alors que j'avais bien le #include<stdlibs> ) du coups j'ai choppé la fonction sur le net :
[...]
 
Et ça marche bien apparemment, merci :D
 
edit : Par contre je me demande, les diverses opérations appliqués à result et next sont faites au hasard, où y'a une logique à tout ça :??:


 
Quand quelqu'un pose une question sur les générateur aléatoires et que je suis d'humeur taquine, je conseille de se référer au livre "The Art Of Computer Programming" de Donald Knuth, plus particulièrement le volume 2 (Semi-numerical algorithms)

Reply

Marsh Posté le 12-11-2011 à 10:54:56   

Reply

Marsh Posté le 12-11-2011 à 22:04:50    

Je demandais juste ça comme ça, je veux pas écrire moi-même de fonctions aléatoire :D
 
Merci pour l'info quand même :jap:


---------------
Perhaps you don't deserve to breathe
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed