Rechercher : dans
Par :

[C/C++] Générer beaucoup de nombres aléatoire

Dernière réponse le 3 jui 2008 à 19:50:15 Ortoli, le 15 fév 2007 à 00:14:12 
 Signaler ce message aux modérateurs

B'jour les gens,

Bon, je crains que ça fasse noube de demander, d'autant que vu le nombre de réponses sur les forums... Je sais, j'ai été modo moi aussi, et je pense bien avoir tout essayé. Enfin, non, pas tout, puisque je n'ai pas encore trouvé ;)

Il faut que je génère un grand nombre de nombres aléatoires (simulation de lois normales, si vous voulez tout savoir), le tout en C/C++.

Alors, au début du main, une seule fois :

srand((unsigned int) time(NULL));


Un flottant entre 0 et 1 me suffirait parfaitement - donc
pif = (float)rand() / ((float)RAND_MAX + 1.0) ;


Le problème est que je génère pif50 fois à la suite pour avoir une loi normale (théorème central limite, pour ceuces que ça intéresse), puis 2000 fois, puis re-1825 fois (5 * 365). Et, comme vous vous en doutez, ben je tombe toujours sur les mêmes nombres.

La seule solution que j'ai trouvée pour le moment est d'attendre une seconde, et pas moins, (Sleep(1000);) entre chaque tirage - ce qui n'est pas possible, à moins d'avoir trente ans à paumer...

Retirer la graine à chaque tirage (genre
for (i) {srand (i) ; rand();}
) ne fonctionne pas non plus.

Une idée, quelqu'un ?
Configuration: Windows XP
Firefox 1.5.0.9

Meilleures réponses pour « [C/C++] Générer beaucoup de nombres aléatoire » dans :
Générer des nombres aléatoires efficacement avec rand() Voir Générer des nombres aléatoires efficacement avec rand() Vous avez peut-être remarqué qu'en C, en utilisant la fonction rand() de la bibliothèque standard, vous obtenez des résultats décevants, trop souvent les mêmes. Prenons un exemple, vous...
Vérifier si un nombre entier est un nombre premier en C VoirDéfinition nombre premier Algorithme 1 : les diviseurs compris entre 2 et N-1 seront testés Algorithme 2 : les diviseurs pairs ne seront pas testés, la recherche se limitant aux diviseurs impairs Algorithme 3 : les diviseurs impairs jusqu'à la...
Représentation des nombres entiers et réels VoirReprésentation d'un nombre dans un ordinateur On appelle représentation (ou codification) d'un nombre la façon selon laquelle il est décrit sous forme binaire. La représentation des nombres sur un ordinateur est indispensable pour que celui-ci...

1

mamiemando, le 15 fév 2007 à 03:10:02
  • +1

Ah oui mais en fait c'est parce que la graine devrait être initialisée une et une seule fois
http://www-fourier.ujf-grenoble.fr/~parisse/tdp0/node55.html­

Bonne chance

Répondre à mamiemando

2

Char Snipeur, le 15 fév 2007 à 09:05:19
  • +1

Salut.
Je pense que le générateur de nombre aléatoire standard n'est pas suffisant pour ce que tu veux faire.
Je pense qu'il ajouter une nouvelle fonction.
J'en ai trouvé une, sur la Gnu Scientific Library (GSL 1.5) qui comporte plusieurs fonctions random. Peut être seraient elles mieux... Salutation !
Char Snipeur

Répondre à Char Snipeur

3

mamiemando, le 15 fév 2007 à 10:09:17

Sinon en boost il y a aussi des outils intéressant pour générer des nombres aléatoire, et même simplement avec la STL

Répondre à mamiemando

4

Stupeflip, le 15 fév 2007 à 10:29:14

La fonction rand n'est pas une réelle fonction aléatoire, elle génère un nombre à partir d'un algo compliqué qui tire sa variable à partir du processeur (je crois que c'est l'horloge mais pas sûr).

Pour avoir un semblant de random sur 2000 valeurs assez rapidement, le plus simple (mais c'est de la bidouille), c'est d'affecter des coefficients rand () les uns aux autres, par exemple tu fais un cosinus d'un rand multiplié par un rand etc etc...
Par contre il faudra déterminer les valeurs max et min en pratique car les multiplications déportent la place de la virgule souvent (genre tu peux passer de 0.X à 0.00X) et il faut adapter aux valeurs dont tu as besoin. Attention aux additions, n'oublie pas de tester si tout rand sort 1 (fonctions magiques pour les additions : cos et sin !)

Voilou

Répondre à Stupeflip

5

Ortoli, le 15 fév 2007 à 12:15:10

'rci à tous !

Bon, alors, effectivement, le rand() suffisait pas. Apparemment, quand il a besoin de tout plein de valeurs au pif rapidement, il reprend certaines d'avant (d'où une sorte de période, des séquences de 50 qui se répètaient plusieurs fois). Ca, un cycle possible, une fonction pas super entropique => yapabon.

Pour répondre, dans l'ordre...

Mamiemando, effectivement, le srand(time(0)) ne se fait qu'une seule fois - c'était mon cas ;) Je n'ai pas cherché avec boost, ayant trouvé avant... A creuser, je le garde dans un coin.

Char Snipeur, j'étais aussi tombé sur la GSL, mais... même réponse que mamiemando, trouvé avant, faudrait creuser, toussa.

Stupeflip, après m'êtrepris la tête dessus pendant 4h, j'ai même ressorti le Knuth, le Schneier et toute la clique. Apparemment, von Neumann aurait dit "Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin." et comme c'était pas la moitié d'un imbécile, j'ai laissé tomber la méthode.

Quoiqu'il en soit, j'ai trouvé au hasard d'un forum le bout de code suivant :

unsigned long prng(unsigned long state)
{
 return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}

(apparemment utilisé par entre autres vlc pour les sons). Je n'ai pas tout pigé, une sorte de /dev/random pour les pauvres ?

En gros, si ça peut servir à quelqu'un :
-> srand((unsigned int) time(NULL)); dans le main au tout début
-> cette fonction prng() {}
-> prng(rand()) pour avoir un nombre au pif entre -2^31 et 2^31

Répondre à Ortoli

6

pom, le 15 fév 2007 à 12:24:48

Salut, quand tu fais pif = (float)rand() / ((float)RAND_MAX + 1.0) ; tu génère un nombre pseudo-aléatoire suivant la loi uniforme et non la loi normale. Voici ce que je fais pour la loi normale :

#define TWOPI (6.2831853071795864769252867665590057683943387987502) /* 2 * pi */

/* 
   RAND is a macro which returns a pseudo-random numbers from a uniform
   distribution on the interval [0 1]
*/
#define RAND (rand())/((double) RAND_MAX)

/* 
   RANDN is a macro which returns a pseudo-random numbers from a normal
   distribution with mean zero and standard deviation one. This macro uses Box
   Muller's algorithm
*/
#define RANDN (sqrt(-2.0*log(RAND))*cos(TWOPI*RAND))


double NormalDistribution(double mu,double sigma)
{
/*
   This function returns a pseudo-random number from a normal distribution with
   mean equal at mu and standard deviation equal at sigma > 0
*/
  if(sigma<=0.)
  {
    fprintf(stderr,"Error in file %s line %u function %s : sigma must be > 0\nExit program\n",__FILE__,__LINE__,__FUNCTION__);
    MPI_Finalize();
    exit(EXIT_FAILURE);
  }
  
  return (mu+sigma*RANDN);

}


et tu fais ensuite une boucle for pour tirer 50000 tirages.

Répondre à pom

7

Char Snipeur, le 15 fév 2007 à 17:28:15

Comprend pas...
pour moi le &0xffffffffL reviens à ne rien faire car un 'et' bit à bit avec que des '1'...
ensuite, je voi pas ou est l'aléatoire, si tu prend deux foi le même "state", tu aura deux foi le même 'prng'. Tu pourrai traduire la phrase de Von Neumann ? Salutation !
Char Snipeur

Répondre à Char Snipeur

8

bebeto, le 15 fév 2007 à 19:51:04

// Tri selection
////////////////
static Liste Tri_Selection_Liste(Liste l)
{
if (l == null)
return null ;

// Recherche du minimum : attention au decalage d'un cran de l1 et l2
Liste l1 = l, l2 = null ; ;
int min = l.elt ;
while (l1.suivant != null) {
if (l1.suivant.elt < min) {
min = l1.suivant.elt ;
l2 = l1 ;
}
l1 = l1.suivant ;
}

// On supprime le minimum de la liste
if (l2 == null) {
l.suivant = Tri_Selection_Liste(l.suivant) ;
return l ;
}
else {
l1 = l2.suivant ;
l2.suivant = l2.suivant.suivant ;
l1.suivant = Tri_Selection_Liste(l) ;
return l1 ;
}
}

// Tri insertion
////////////////
static Liste Tri_Insertion_Liste(Liste l)
{
// On prend le premier element
Liste l2 = l ;
l = l.suivant ;
l2.suivant = null ;

// On ajoute les elements suivants
while (l != null) {
if (l.elt < l2.elt) {
Liste l1 = l ;
l = l.suivant ;
l1.suivant = l2 ;
l2 = l1 ;
}
else {
Liste l1 = l ;
l = l.suivant ;
l1.suivant = null ;
Ajout_Trie_Liste(l2, l1) ;
}
}
return l2 ;
}

// Fonction d'ajout d'un element dans une liste triee
static void Ajout_Trie_Liste(Liste l, Liste l1) {
if (l.suivant == null) {
l.suivant = l1 ;
}
else if (l1.elt < l.suivant.elt) {
l1.suivant = l.suivant ;
l.suivant = l1 ;
}
else
Ajout_Trie_Liste(l.suivant, l1) ;
}
bonsoir tu peut m'aider a trduire ce code de java au pascal
merci

Répondre à bebeto

9

Stupeflip, le 16 fév 2007 à 11:42:21

C'est un masque le 0xffffff non ?
Sinon la phrase c'est un truc du genre : Toute personne qui s'intéresse aux méthodes arithmétiques pour trouver des algo aléatoires est, bien sur, un peu fou ! :p

Répondre à Stupeflip

10

Char Snipeur, le 16 fév 2007 à 15:50:49

Ok, merci pour la traduction.
La méthode prng resemble à une méthode arithmétique, ou il y a un truc qui m'échape.
0xffffffff c'est surement un masque, mais pour moi c'est un masque qui fait rien, qui laisse tout passer car tout les bit du nombre sont à 1. Si qqun pouvai expliquer cette fonction prng, pasque pour moi elle est bidon. Salutation !
Char Snipeur

Répondre à Char Snipeur

11

bebetoalvaro, le 16 fév 2007 à 16:20:59

Tu peux me repondre a ma question
c comment trier les listes chainee
merci

Répondre à bebetoalvaro

13

Char Snipeur, le 17 fév 2007 à 16:28:34

Salut bebe,
je ne répondrai pas à ta question ici.
Déjà parceque ce n'est pas le sujet du présent message (random tout ça) Ensuite, parceque tu ne pose pas de question. Tu demande de l'aide, je veux bien t'en fournir, mais faire de la traduction, j'ai pas envie de la faire à ta place.
donc, ouvre un message, pose une question claire et précise, precise Java<->pascal dans ton titre, et je verrai à te répondre. Salutation !
Char Snipeur

Répondre à Char Snipeur

12

lirey83, le 17 fév 2007 à 14:24:06

Il y a quantité d'algo sur Internet. Cherche "Random number" avec Google et tu en auras une palanqué. Exemple :
http://www.boost.org/libs/random/

Y a aussi "numerical recipes" ...

Répondre à lirey83

14

Benur29, le 18 fév 2007 à 14:58:38

Fais un tit tour sur mon site :
http://b.rock.monsite.orange.fr/
rubrique développements

Répondre à Benur29

15

Ortoli, le 18 fév 2007 à 22:27:19

Bon, ben merci à tous ! Comme je l'ai dit - sans que l'on arrive à comprendre pourquoi, mais je creuse, je vous tiens au courant - j'ai trouvé, et grâce à ce qu'il m'a été proposé plus haut, il me reste quelque pistes. Reste plus qu'à trouver comment marquer le message en "résolu".

Répondre à Ortoli

16

vkf, le 3 jui 2008 à 11:29:06

Sinon tu fais un tableau de nombres aléatoires, tu prends au hasard le nombre d'une case de ce tableau et tu le remplac e par un autre nombre aléatoire.

un site intéressant sur le sujet :
http://www.games-creators.org/...

Répondre à vkf

17

 mamiemando, le 3 jui 2008 à 19:50:15

Depuis un an et demi je pense qu'il a trouvé ;-)

Répondre à mamiemando