Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
913 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

fontion rand en c++

n°1041909
Taz
bisounours-codeur
Posté le 10-04-2005 à 13:40:14  profilanswer
 

Reprise du message précédent :

Code :
  1. def random(self):
  2.         """Get the next random number in the range [0.0, 1.0)."""
  3.         # Wichman-Hill random number generator.
  4.         #
  5.         # Wichmann, B. A. & Hill, I. D. (1982)
  6.         # Algorithm AS 183:
  7.         # An efficient and portable pseudo-random number generator
  8.         # Applied Statistics 31 (1982) 188-190
  9.         #
  10.         # see also:
  11.         #        Correction to Algorithm AS 183
  12.         #        Applied Statistics 33 (1984) 123
  13.         #
  14.         #        McLeod, A. I. (1985)
  15.         #        A remark on Algorithm AS 183
  16.         #        Applied Statistics 34 (1985),198-200
  17.         # This part is thread-unsafe:
  18.         # BEGIN CRITICAL SECTION
  19.         x, y, z = self._seed
  20.         x = (171 * x) % 30269
  21.         y = (172 * y) % 30307
  22.         z = (170 * z) % 30323
  23.         self._seed = x, y, z
  24.         # END CRITICAL SECTION
  25.         # Note:  on a platform using IEEE-754 double arithmetic, this can
  26.         # never return 0.0 (asserted by Tim; proof too long for a comment).
  27.         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0


 
tiré des sources du module random de python. Cette algorithme à l'air très intéressant. Je pense que tu peux le reprendre tel quel. La graine est un triplet. Reste le problème du signe.

mood
Publicité
Posté le 10-04-2005 à 13:40:14  profilanswer
 

n°1041917
Taz
bisounours-codeur
Posté le 10-04-2005 à 13:51:46  profilanswer
 

Code :
  1. class WHRandom
  2. {
  3. private:
  4.   unsigned short x, y, z;
  5. public:
  6.   WHRandom(unsigned short xx, unsigned short yy, unsigned short zz)
  7.     : x(xx), y(yy), z(zz)
  8.   { }
  9.   double operator()()
  10.   {
  11.     x = (171 * x) % 30269;
  12.     y = (172 * y) % 30307;
  13.     z = (170 * z) % 30323;
  14.     return fmod(x/30269.0 + y/30307.0 + z/30323.0, 1.0);
  15.   }
  16. };

ça va vite :)

n°1042545
coincoin13​07
Posté le 11-04-2005 à 02:05:10  profilanswer
 

Merci Taz. Je prend ta classe, elle me servira surement. En attendant, javais trouvé une solution en faisant:
boule[i].posx = ((float)rand() /18000)-0.9; et ça me rempli mon ecran bien comme il faut, sans que sa depasse. Jy suis allé a taton en fait...
 
Voila voila..
Merci @+ ;)

n°1042603
Taz
bisounours-codeur
Posté le 11-04-2005 à 09:26:24  profilanswer
 

sauf que la répartition n'est pas uniforme du tout ... et c'est quoi ce 18000 ? RAND_MAX / 2 ?
 
comme je t'ai dit
 
2.0 * rand() / RAND_MAX - 1.0 ce n'est pas bon, car la répartition n'est pas uniforme, mais alors pas du tout.

n°1043005
nathan_g
Posté le 11-04-2005 à 14:48:56  profilanswer
 

On peut aussi prendre :
 

Code :
  1. // double pseudo aléatoire, à valeur entière, entre - RAND_MAX (non compris) et RAND_MAX (non compris) :
  2. a = 2.0*rand() - (double) RAND_MAX
  3. // double pseudo aléatoire entre -1 (non compris) et 1 (non compris) :
  4. b = a/((double) RAND_MAX + 1.0)
  5. // double pseudo aléatoire entre -1 (compris) et 1 (compris) :
  6. c = a/((double) RAND_MAX)


 
 
Ca doit marcher et les valeurs sont régulièrement espacées. Il y a peut être néanmoins des problèmes d'arrondis parfois qui font que c peut sortir, très légèrement de [-1,1] avec des divisions de deux double égaux.

n°1043226
Taz
bisounours-codeur
Posté le 11-04-2005 à 17:08:10  profilanswer
 

c'est toujours mauvais niveau répartission et à cause du trou vers 0 ...

n°1043294
nathan_g
Posté le 11-04-2005 à 18:00:18  profilanswer
 

Comment ça ?
 
rand() renvoie un entier entre 0 (compris) et RAND_MAX (compris). Donc a est bien un " double " entre - RAND_MAX (compris) et RAND_MAX (compris) (il y a une rreur dans ma réponse, dans ce commentaire ;) ).
 
Les valeurs de a se succèdent de 2 en 2 et prennent des valeurs égales à des entiers.
 
Finalement, b est un double compris entre -1 (non compris) et 1 (non compris). Ses valeurs extrèmes sont :
 
- RAND_MAX/(RAND_MAX+1)  (valeur légèrement supérieure à -1)
 
et :
 
RAND_MAX/(RAND_MAX+1)    (valeur légèrement inférieure à 1)
 
Et les valeurs de b sont régulièrement réparties avec un incrément de 2/(RAND_MAX+1).
 
Au final, on a donc bien des valeurs régulièrement réparties sur l'intervalle [-1,1]. Si RAND_MAX est pair, 0 peut être sortie de b, sinon, on ne sort que les valeurs proches -1/(RAND_MAX+1) et 1/(RAND_MAX+1).
 
Cependant, je ne vois pas trop la nécessité de pouvoir sortir 0 si on cherche à générer des double entre -1 et 1.
 
Le raisonnement est identique pour c qui est équiréparti entre -1 et 1 et peut atteindre les valeurs extrèmes.

n°1043349
Taz
bisounours-codeur
Posté le 11-04-2005 à 19:13:48  profilanswer
 

les valeurs oui, mais la représentation d'un float non.

n°1043663
nathan_g
Posté le 12-04-2005 à 08:08:48  profilanswer
 

Désolé, mais je ne comprends pas trop ton problème de réprésentation des float. Qu'est ce qui pose problème ? En remplaçant les double par des float :
 

Code :
  1. // float pseudo aléatoire, à valeur entière, entre - RAND_MAX (non compris) et RAND_MAX (non compris) :  
  2. a = 2.0*rand() - (float) RAND_MAX 
  3. // float pseudo aléatoire entre -1 (non compris) et 1 (non compris) :  
  4. b = a/((float) RAND_MAX + 1.0)
  5. // float pseudo aléatoire entre -1 (compris) et 1 (compris) :  
  6. c = a/((float) RAND_MAX)


 
On obtient des float pseudo-aléatoires (c'est ça que tu cherchais ?), équirépartis.
 
Je pense que le problème dont tu parlais se situait à un autre niveau mais je ne vois pas bien de quoi il s'agit.

n°1043739
Taz
bisounours-codeur
Posté le 12-04-2005 à 09:48:18  profilanswer
 

et ben documentes toi sur le format de nombres flottants.

mood
Publicité
Posté le 12-04-2005 à 09:48:18  profilanswer
 

n°1044236
nathan_g
Posté le 12-04-2005 à 14:33:47  profilanswer
 

Désolé mais je ne vois toujours pas en quoi il y a problème. Je ne comprends pas non plus en quoi la différence entre float et double change qqch (taille de la mantisse, de l'exposant position du signe ?) dans ce problème !

n°1044283
Taz
bisounours-codeur
Posté le 12-04-2005 à 14:57:27  profilanswer
 

Je parle de flottants. double ou float, c'est la même chose.
Documente toi sur les histoires de trucs dénormalisés et sur le trou près de 0


Message édité par Taz le 12-04-2005 à 14:58:24
n°1048221
tyrion42
Posté le 15-04-2005 à 03:13:12  profilanswer
 

Une implémentation random que j'utilise (par contre, pas testé sur [-1, 1]
 
http://ktd.club.fr/programmation/cpp-random.php

n°1052471
oulddah
Posté le 19-04-2005 à 16:35:41  profilanswer
 

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
 
/* afficher un nombre aleatoire entre 0 et variable*/
int main(void)
 {
    randomize();
    printf("voilà un nbr aléatoire entre 0 et varible: %d\n", random (variable));
    return 0;
}


---------------
oualataSoft
n°1052533
kaktusBigO​ne
Posté le 19-04-2005 à 16:59:04  profilanswer
 

Et bien je te propose cela :
 
 

Code :
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <time.h>         // <---  Pas oublier  
  4. using namespace std;
  5. int Random(const int & );
  6. int main()
  7.      {
  8.      srand(unsigned(time(0)));   // <---- Ca non plus     
  9.      const int nombremax = 100;  // Nombre maximum à atteindre
  10.    
  11.    
  12.      for (int i=0; i<50; i++) cout << Random(nombremax) << endl;
  13.    
  14.      
  15.      system("PAUSE" );
  16.      return 0;
  17.      };
  18.    
  19. int Random(const int &nombremax)
  20.      { return static_cast <int> (rand()%nombremax + 1); }


 
 
 
 
Là tu as une série de 50 nombres générés entre 1 et 50.
 
Bon courage, oublie-pas le include et le srand(unsigned(time(0))).

n°1052542
kaktusBigO​ne
Posté le 19-04-2005 à 17:04:39  profilanswer
 

Euh entre 1 et 100 pardon :).

n°1052620
Taz
bisounours-codeur
Posté le 19-04-2005 à 17:53:18  profilanswer
 

c'est une blague ? commence par lire le topic :o
 
 
superbe cast d'ailleurs ...
franchement t'as pas honte de sortir un truc comme ça ?


Message édité par Taz le 19-04-2005 à 17:54:00
n°1052683
Tarabiscot​e
Posté le 19-04-2005 à 18:43:50  profilanswer
 

Et pourquoi tu fais :
#include <cstdlib>
et après :
#include <time.h>
 
Tu aurais pu continuer sur la lancé :
#include <ctime>

n°1052749
kaktusBigO​ne
Posté le 19-04-2005 à 19:26:47  profilanswer
 

Taz : achète toi des lunettes (2ème fois), tu sais tu peux avoir une deuxième paire pour pas cher :
 
Topic lancé par belgarion :
je cherche a faire une fontion random entre 1 et la valeur dans une variable  
 
faut que je fasse quoi comme code.
 
 
C'est pas ce que j'ai fait hmm?? Bon 2001 ok, mais c récurrent comme question.
Maintenant ouvre un autre post si tu veux causer Python, t pas sur le bon forum.
Et arrête de me chercher stp c lassant ...
 
 
Tarabiscote : merci pour le bon include, ça sera fait.

n°1052755
Taz
bisounours-codeur
Posté le 19-04-2005 à 19:29:33  profilanswer
 

L I S C E T O P I C

n°1053069
blastman
just me !
Posté le 20-04-2005 à 02:11:45  profilanswer
 

ça a l'air de chauffer ici [:aganemnon]
 
c'est quoi l'embrouille [:apo]


Message édité par blastman le 20-04-2005 à 02:14:17

---------------
http://www.blastmanu.info
n°1053113
Taz
bisounours-codeur
Posté le 20-04-2005 à 08:24:52  profilanswer
 

y a pas d'embrouille. Sauf que ce topic rassemble les bonnes techniques pour obtenir des nombres pseudos aléatoires avec de bonnes implémentations, et là on on a gus qui débarque avec la PIRE des méthodes codée n'importe comment.
 
Que tout le monde note bien le static_cast<int>( ... ) : dorénavant, suivons tous les conseils de kaktusBigOne, écrivons;
 
for(int i = static_cast<int>(0); i < static_cast<int>(10); i++)
...

n°1053262
kaktusBigO​ne
Posté le 20-04-2005 à 10:52:38  profilanswer
 

Taz a raison ...
 
J'aurai dû enlever le cast en int car rand()%100 + 1 renvoie un entier.
Initialement j'avais un type float -(rand()%100 +1) multiplié par un pourcentage variable- mis pour les besoins de mon programme d'où mon cast...
Le cast n'a donc plus lieu d'être.  
 
Faut savoir reconnaître ses erreurs et étourderies, c'est comme ça qu'on apprend :)
 
 
Bonne journée.

n°1053317
Taz
bisounours-codeur
Posté le 20-04-2005 à 11:12:29  profilanswer
 

MAIS LE PROBLÈME C'EST TON ALGORITHME !

n°1053607
blastman
just me !
Posté le 20-04-2005 à 14:47:17  profilanswer
 

j'ai pas tout lu, j'avais la flemme...
 
mais quand j'utilise la fonction rand() et que je veux un que ça me génère un nombre dans un intervalle donné j'utilise ça:
 

Code :
  1. int Interv_Alea(int a,int b)
  2. {
  3.     return a+(int)((float)rand()*(b-a+1)/(RAND_MAX+1));
  4. }


 
 


---------------
http://www.blastmanu.info
n°1053611
Taz
bisounours-codeur
Posté le 20-04-2005 à 14:48:38  profilanswer
 

si a < b

n°1053621
blastman
just me !
Posté le 20-04-2005 à 14:56:33  profilanswer
 

oups, je viens de m'apercevoir que ce code est correct sous windows mais pas sur GNU/Linux mais il doit y a avoir une petite connerie a modif rien de méchant...


---------------
http://www.blastmanu.info
n°1053926
nathan_g
Posté le 20-04-2005 à 17:09:41  profilanswer
 

Ton  
 

Code :
  1. return a+(int)((float)rand()*(b-a+1)/(RAND_MAX+1));


 
ne devrait-il pas plutot être :
 

Code :
  1. return a+(int)((float)rand()*(b-a+1)/(RAND_MAX+1.));


 
afin de forcer le calcul intermédiaire de sommation avec 1 à se faire en double (ou float) ? En effet, la sommation de 1 sur RAND_MAX, qui doit correspondre à la valeur maximale d'un int, doit, si on reste sous forme int, te donner - RAND_MAX (ou qqch de similaire).
Si tu as une erreur sous Linux, tu peux vérifier que les étapes de calcul intermédiaires sont correctes.

n°1130937
Profil sup​primé
Posté le 25-06-2005 à 20:45:23  answer
 

petite question pr gros pb :D
je ne cree pas de nouveau topic, car le pb est sensiblement le meme qu'ici, mis a part le fait que ce soit en c :D
bref, le but du jeu est de generé x nombres aleatoires compris entre 0 et 100, 100 exclus, et x entre 0 et 100, 100 exclu (40 par defaut). le but etant de cibler des coordonnées d'une matrice 10 x 10 allouée sur la forme d'un tableau de 100
 
ca marche tres bien (j'ai lu ce topic et qq autres, c moi ou personne ne fait appel a gettimeofday() ? ...)
bref, pr mon appli, ca donne en pseudo code
 

Code :
  1. int my_rand()
  2. {
  3.    return ((rand() + gettimeofday()) % 100);
  4. }


 
jusque la, ca genere des nombres aleatoires, mais avec une proportion anormalement elevée de nombre pair (70/80 % en moyenne)
aucun souci, on modifie ca:
 
 

Code :
  1. int     my_rand()
  2. {
  3.    int  res;
  4.  
  5.    res = (rand() + gettimeofday()) % 99;
  6.    if (res > 50)
  7.       res++;
  8.    return res;
  9. }


 
la, c au poil, la proportion de nombres pairs et impairs est plus que correcte :)
mais qd graphiquement on visualise la map, on voit clairement que certaines zones sont plus peuplés que d'autres, ce qui revient a dire que les nombres generés s'attirent, ie on se retrouve avec des 1, 2, 3, 11, 12, 13, 21, 22, 23 et rien dans 7, 8, 9, 17, 18, 1927, 28,  29 et ce apres plusieurs tests  :heink:  :pt1cable:  
le petit hic, c que lorsque je diminue mon x du debut de l'ennoncé, aucun des nombres ne se rapproche des autres, sauf cas exceptionnel.  
le pb est mi info / mi denombrement  :whistle: mais je le precise, le but de ma question est bien de generé des nombre aleatoirement, non pas de gagner a tous les coup au loto  :whistle:  
je pige pas comment il fait pour sortir des nombres si proche sur la carte ...
 
edit --> derniere precision, une solution ne necessitant pas forcement un ordinateur quantique serai appreciée :D :jap:


Message édité par Profil supprimé le 25-06-2005 à 20:50:45
n°1130976
Tarabiscot​e
Posté le 25-06-2005 à 21:36:14  profilanswer
 

gettimeofday() (ou une autre fonction) ne devrait être utilisé qu’une fois pour l’initialisation :
srand(gettimeofday()) ;
 
Ensuite le modulo (%) ne garanti pas l’équiprobabilité
Petit exemple : imaginons que rand renvoie un nombre entre 0 et 15 (c’est uniquement pour la compréhension de l’exemple), et que tu veux un nombre entre 0 et 9 si tu fais :
rand() % 10;
Tu vas obtenir :
Rand :
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
Résultat du modulo :
00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05
Donc 2 fois plus de chance d’avoir un nombre inférieur ou égal à 5 que supérieur.
 
En utilisant : (int) (10.0*rand()/(RAND_MAX+1.0));
Résultat (possible) :
00 00 01 02 02 03 04 05 05 06 07 07 08 09 09 10
L’avantage c’est qu’on a autant de chance d’avoir un nombre petit ou grand, inconvénient certains nombres sortent plus souvent.
 
Une solution pourrait être de refaire un tirage quand ce nombre est trop grand en utilisant éventuellement un masque pour diminuer le nombre de cas défavorables, le problème de cette solution est le temps mis pour trouver un nombre. (réservé aux cas extrême)


Message édité par Tarabiscote le 25-06-2005 à 21:38:28
n°1130982
Profil sup​primé
Posté le 25-06-2005 à 21:51:27  answer
 

Tarabiscote a écrit :

gettimeofday() (ou une autre fonction) ne devrait être utilisé qu’une fois pour l’initialisation :
srand(gettimeofday()) ;
 
Ensuite le modulo (%) ne garanti pas l’équiprobabilité
Petit exemple : imaginons que rand renvoie un nombre entre 0 et 15 (c’est uniquement pour la compréhension de l’exemple), et que tu veux un nombre entre 0 et 9 si tu fais :
rand() % 10;
Tu vas obtenir :
Rand :
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
Résultat du modulo :
00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05
Donc 2 fois plus de chance d’avoir un nombre inférieur ou égal à 5 que supérieur.
 
En utilisant : (int) (10.0*rand()/(RAND_MAX+1.0));
Résultat (possible) :
00 00 01 02 02 03 04 05 05 06 07 07 08 09 09 10
L’avantage c’est qu’on a autant de chance d’avoir un nombre petit ou grand, inconvénient certains nombres sortent plus souvent.
 
Une solution pourrait être de refaire un tirage quand ce nombre est trop grand en utilisant éventuellement un masque pour diminuer le nombre de cas défavorables, le problème de cette solution est le temps mis pour trouver un nombre. (réservé aux cas extrême)


ok pr le gettimeofday
pr le %, le nombre generé est entre 0 et la borne max, bien plus grand que 100, donc modulo 100, ca a autant de change d'etre > que < 100, je me trompe ?
de toute facon, la n'est pas le pb, les nb generés le sont  equitablement reparti par rapport a 50.

n°1595363
kerik
Posté le 03-08-2007 à 11:27:16  profilanswer
 
n°1630554
iery
Piwout .......?
Posté le 24-10-2007 à 23:58:46  profilanswer
 

Bonjour
J'ai des probleme pour générer des nombres aléatoire, en effet j'ai une fonction qui les génère mais je dois générer deux suites de nombre aléatoire hors ca me génère là meme suite (ca ne m'étonne pas je pense que c'est a cause d'une initialisation du générateur de nombres pseudos-aleatoires qui est la meme puisque le programme n'est lancé q'une fois)
Je vouidrais savoir comment résoudre ce problème en initilisant une 2eme fois ma suite (je ne peu pas générer une grande suite et la divisé en deux car la c'est niveau méthode de conception que ca me gène,meme si ca marcherait)
 
Merci (le sujet a quand meme 7ans :))

n°1630559
Elmoricq
Modérateur
Posté le 25-10-2007 à 00:04:01  profilanswer
 

Il te suffit de générer une nouvelle graine entre les deux tirages.
Regarde du côté de la fonction srand().

n°1630715
iery
Piwout .......?
Posté le 25-10-2007 à 10:30:08  profilanswer
 

effectivement le pb viens de là mais je ne connais qu'un parametre a donné a cette fonction,  

Code :
  1. srand(time(NULL))


et l'init est donc tjrs la meme, y aurai t'il un autre moyen de l'init ?

n°1630716
Elmoricq
Modérateur
Posté le 25-10-2007 à 10:32:17  profilanswer
 

L'argument donné à srand() permet de regénérer les prochains tirages. On donne habituellement time(NULL) parce que c'est pratique : time(NULL) retourne le nombre de secondes écoulées entre maintenant et The Epoch (01/01/1970). Ça permet d'avoir des tirages différents lorsque l'on démarre plusieurs fois un même programme, sauf si plusieurs occurences démarrent à la même seconde évidemment. [:dawao]
Mais disons que c'est bien suffisant dans la majorité des cas.

 

Dans ton cas, ça peut effectivement ne pas suffir, à toi d'imaginer un moyen de fournir une graine qui-va-bien [:dawa]


Message édité par Elmoricq le 25-10-2007 à 10:34:07
n°1630726
iery
Piwout .......?
Posté le 25-10-2007 à 10:41:38  profilanswer
 

ok, mes initialisation sont faite en meme tps, je vais allé voir dans les time.h (ou un autre truc du style)  si je trouve pas quelle chose de différent

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
générateur de nombre aléatoire sous VC++ meilleur que rand ?[C] rand()
Plus de sujets relatifs à : fontion rand en c++


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR