| |||||
| Dernière réponse | |
|---|---|
| Sujet : générateur de nombre aléatoire sous VC++ meilleur que rand ? | |
| z51 | C'est un peu hors sujet, mais certains chipsets Intel incluent un générateur de nombres aléatoires, appelé RNG.
Son accès n'est pas immédiat, il faut développer sa propre interface ... Plus d'infos sur : http://developer.intel.com/design/security/rng/rng.htm Voilà c'était juste pour info. |
| Aperçu |
|---|
| Vue Rapide de la discussion |
|---|
| z51 | C'est un peu hors sujet, mais certains chipsets Intel incluent un générateur de nombres aléatoires, appelé RNG.
Son accès n'est pas immédiat, il faut développer sa propre interface ... Plus d'infos sur : http://developer.intel.com/design/security/rng/rng.htm Voilà c'était juste pour info. |
| BifaceMcLeOD | up ! D'autres topics référencent celui-ci... |
| chin jo | trop gentil !!!
je teste (demain, je ne suis pas à mon bureau aujourd'hui) ET j'essaye de comprendre avec la doc. La reconnaissance éternelle n'est pas loin... |
| BifaceMcLeOD | Bon, si j'ai bien compris, dans ton cas, tu dois pouvoir te contenter des fonctions srand48() et drand48().
Les fonctions qui attendent un tableau de 3 entiers en argument sont utiles si tu veux faire utiliser un générateur aléatoire indépendant à différents threads en parallèle. Ce tableau est une sorte de "contexte" pour ces fonctions, qu'elles utilisent d'une fois sur l'autre ; mais tu n'as pas besoin d'aller voir ce qu'il contient, tu te contentes de l'initialiser avec rand48() et de le passer à chaque appel qui génère un nouveau nombre aléatoire. Mais de toute façon, si tu n'a qu'un seul thread (ce qui a l'air d'être le cas), le module est capable de gérer ça pour toi. Pour utiliser mon module, tu peux mettre les 5 fichiers dans ton répertoire de travail (o2_rand48.c et int48.cc sont les 2 fichiers à faire compiler au compilateur). Et dans chaque fichier C/C++ qui utilise le générateur aléatoire (il ne devrait pas y en avoir des masses), tu mets un : #include "rand48.h" Ensuite, tu peux utiliser ces fonctions comme si elles faisaient partie de la librairie standard (et donc remplacer les appels actuels à srand() et rand() par des appels à srand48() et drand48()). [edit]--Message édité par BifaceMcLeOD--[/edit] |
| BifaceMcLeOD | chin jo> Ben yavékad'-mander ! :sarcastic: :D Bon, c'est vrai que ça manque un peu de doc utilisateur, ce que je t'ai envoyé. Normalement un "man drand48" doit résoudre le problème, mais sur NT, évidemment... :o Voici la doc MAN des fonction drand48. Tu devrais en déduire la doc des miennes assez facilement :
|
| chin jo | Suite du problème…
Rappel : J'ai besoin de nombres aléatoires pour une simulation (émission et dépôt de particules). La fonction rand() est appelée plusieurs fois pour chaque particule simulée, pour des caractéristiques différentes (position, vitesse, énergie, angle...). Le nombre de caractéristique par particule variant suivant la particule considérée une "périodicité" due à la faible portée de rand_max comparée au nombre de particules simulées n'est pas trop gênante. Cependant pour l'une des caractéristiques il me faut un nombre entre 0 et 1 (inclus) avec un pas plus fin que 1/rand_max Après tests toutes les solutions de type décalage int aleatoire_30(void) { int rnd1,rnd2,rnd_30; rnd1=rand(); //initialiser_aleatoire(); rnd2=rand(); rnd_30=(rnd1<<15|rnd2); return(rnd_30); } sont fausses tant que l'on ne fait pas une réinitialisation entre les appels à rand() ; et ce même en ne conservant que 8 bits des int que rand() renvoie. tirage d'un rand sur 24 bits en 3*8bits avec int aleatoire_24(void) { int rnd1,rnd2,rnd3,rnd_30,cst=255; rnd1=(rand()&cst); rnd2=(rand()&cst); rnd3=(rand()&cst); rnd_24=((rnd3<<16)|(rnd2<<8)|(rnd1)); return(rnd_24); } Une périodicité ressort du fait des appels consécutifs a rand(). La réinitialisation est délicate à effectuer car elle est coûteuse en temps de calcul et il faut faire plus raffiné qu'un appel d'horloge simple car la fonction est appelée à très haute fréquence. Biface McLeO.D. -> J'essaierai volontiers ton code (en fait je compte même beaucoup sur lui...) mais mes quelques connaissances de C ne m'ont pas permis de comprendre comment l'inclure dans ma simul ! Si tu pouvais me dire comment appeler la fonction qui me renvoie un aléatoire sur 48 bit dans mon " C/C++ source file " (visual C++ 6.0, c'est un petit peu fort pour moi et pour faire juste du C, mais je ne désespère pas de faire une interface plus tard) et où placer les fichiers de ton archive je t'en serais très reconnaissant. Merci à tous pour votre aide… |
| BifaceMcLeOD | chin jo> Check your mail... |
| BifaceMcLeOD |
[edit]--Message édité par BifaceMcLeOD--[/edit] |
| tfj57 | Les fonctions srand() et rand() de stdlib.h sont définies comme suit (pour VC++ 6.0 : Win32 Console Application) :
int x=1; void srand(int n) { x=n; } int rand() { x=x*0x343fd+0x269ec3; return((x>>16)&0x7fff); } Comparer avec les fonctions originales, vous allez voir !!! Vu la complexité de ces fonctions, je pense donc qu'il ne faut pas se casser la tête avec ces fonctions originales, il suffit de les redéfinir, par exemple comme suit : unsigned int x=1; // Initialisation void srandx(unsigned int n) { x=n; } // pour un nombre 32 bits inline unsigned int randx() { x=x*0x343fd+0x269ec3; return(x); } // pour un nombre entre [0;1[ inline double drandx() { const double rm=4294967296.0; x=x*0x343fd+0x269ec3; return(x/rm); } On peut aussi modifier les constantes ... Salutations |
| LeMulot |
|
| BENB |
|
| chin jo | bonjour a tous ! tfj57 : pas mal, je n'avais pas pensé à cette méthode, je regarderai ce que ca donne en temps de calcul et en efficacité BifaceMcLeOD : Le prg devra tourner sous NT et 98... La simulation en question porte sur une emission de particules et je tire au minimum 4 aleatoires par particule * entre 40 millions et 5 milliards de particules suivant la précision voulue dans la simul ! ( mais la fonction rand "de base" parait suffir pour 3 de ces 4 tirages ) merci a tous ! |
| BifaceMcLeOD | chin jo> Ce n'est pas forcément une bonne idée de mettre "bout-à-bout" 2 nombres aléatoires. En fait, tout dépend de ce que tu fais.
De combien de nombres aléatoires as-tu besoin ? Si c'est quelques dizaines ou quelques centaines, tu peux y aller, pas de problème. Si c'est plusieurs milliers ou dizaines de milliers, là, il faut que tu changes d'échelle. Un générateur 16 bits n'est plus suffisant, et il faut passer au générateur 48 bits. Si tu es sur UNIX, tu en as un quelque part dans les librairies standard. Si tu es sur NT, dommage... il va falloir t'en programmer un. Si tu es intéressé, je peux te donner ce qu'il faut, j'ai déjà été confronté au problème. |
| tfj57 | Bonjour à toutes et à tous,
En sachant que rand() retourne une valeur positive entre [0;RAND_MAX], on peut écrire : Pour une résolution de 30 bits (si RAND_MAX=0x7fff) : double rm,x1,x2,x; rm=RAND_MAX; x1=rand(); x2=rand(); x=( x1*(rm+1)+x2 ) / ( rm*(rm+1)+rm ); Pour une résolution de 45 bits : double rm,x1,x2,x3,x; rm=RAND_MAX; x1=rand(); x2=rand(); x3=rand(); x=( (x1*(rm+1)+x2)*(rm+1)+x3 ) / ( (rm*(rm+1)+rm)*(rm+1)+rm ); On remarque bien que : - si tous les xi sont tous à 0, alors x sera 0 - si tous les xi sont à RAND_MAX, alors x sera 1 (voir simplification des expressions). Donc x sera un nombre aléatoire de [0;1] Salutations. |
| chin jo | ... je m'interroge : dans stdlib.h j'ai : /* Maximum value that can be returned by the rand function. */ #define RAND_MAX 0x7fff que je n'ai pas réussi à modifier. (refuse de recompiler le .h) sur un vieux borland C j'ai vu qu'il existait la fonction random qui pourrait fonctionner, je vais tester. Concernant la représentation de rand_max : je croyais que c'était 16 bits avec un bit de signe soit 2^15 -1 combinaisons ou bien de 0 a 32867 Veux tu dire que cela serait en fait 32 bits (car int en VC++6)avec 17 bits à éliminer lors de mon décalage ? Désolé de mon piètre niveau en info, je suis de formation physique/microelectronique et je n'ai plus de cours de programmation... Merci pour ta réponse ! |
| BENB | il me semble que rand renvoie un int donc 32 bits...
sinon si rand renvoie un 16bits signe positif, donc 15bits fait (supposant int 32 bits) int rnd1 = rand(); int rnd2 = rand(); int rnd = ((rnd1<<15)|rnd2); // verifier << ou >> sur 30 bits donc positif... PS il n'y a plus (beaucoup) de machines pour lesquelles int est 16 bits... |
| chin jo | La portée de rand n'est que de RAND_MAX, et j'ai besoin de nombres aléatoire entre 0 et 1 ( 1 inclus ou exclus suivant les fonctions ) ayant une meilleure "finesse" que 1/RAND_MAX. (J'entends par la que le pas entre deux aléatoires consécutifs doit être de moins de 1/RAND_MAX.) Voici ce que j'utilise pour le moment : void initialiser_aleatoire(void) { time_t t; srand((unsigned)time(&t)); } double aleatoire_ie(void) { return(((double)rand()/(double)((RAND_MAX)+1))); /* entre 0 et 0.99999..., juste car x/x+1 = 1- 1/x+1 */ } double aleatoire_ii(void) { return(((double)rand()/(double)RAND_MAX)); /* entre 0 et 1 */ } Je pensais mettre deux aleatoires en binaire bout a bout et lire le nombre ainsi formé, mais vu la portée de RAND_MAX qui est codé sur 16 bits, je dois avoir un bit de signe au début qu'il faudrait que j'élimine. Si quelqu'un a une autre méthode (rapide, c'est pour une simul de monte carlo et la fonction va être appelée plusieurs milliards de fois) Merci ! |




