Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Génération de nombres aléatoires

10 réponses
Avatar
Leo
Bonjour,

Comme la lecture de tutoriels et de posts sur le sujet, je m'adresse
a vous pour que vous m'aidiez, en fait je voudrais g=E9n=E9rer des
nombres aleatoires compris entre 10000 et 99999 inclus.

J'ai utilise srand(time(NULL));
et : int variable =3D (int)(rand() / (double)RAND_MAX * (N - 1));
avec RAND_MAX =3D 100000
et N =3D 10000

mais cela me donne des r=E9sultats a 9 chiffres.

Si vous pouviez m'aider,

Merci.

10 réponses

Avatar
James Kanze
Leo wrote:

Comme la lecture de tutoriels et de posts sur le sujet, je m'adresse
a vous pour que vous m'aidiez, en fait je voudrais générer des
nombres aleatoires compris entre 10000 et 99999 inclus.

J'ai utilise srand(time(NULL));
et : int variable = (int)(rand() / (double)RAND_MAX * (N - 1));
avec RAND_MAX = 100000
et N = 10000


D'où est-ce que tu as une implémentation avec RAND_MAX à
10000 ? Je n'en ai jamais vu. (La norme, d'ailleurs, dit que
RAND_MAX vaut au moins 32767 ; dans la pratique, sur une
machine 32 bits, je m'attendrais à une valeur dans les
milliards, pour une implémentation de rand() qui vaut.)

Sinon, je suis assez scéptique de la technique qui passe par des
doubles (au moins qu'on veut des flottants à la fin). Je préfère
quelque chose du genre : « rand() % N ». Dans le cas où N
n'est pas extrèmement petit par rapport à RAND_MAX (et il y a
des implémentations où ce n'est réelement que la minimum
requise), il faut prendre aussi des précautions contre le bias
vers les valeurs plus faibles ; j'utilise normallement quelque
chose du genre :

int const limit = RAND_MAX - RAND_MAX % N ;
int result = rand() ;
while ( result >= limit ) {
result = rand() ;
}

mais cela me donne des résultats a 9 chiffres.


Sans doute tu as faussé la valeur de RAND_MAX quelque part, que
dans ton implémentation, elle est en fait une valeur avec une
dixaine de chifres.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Michel Decima
Bonjour,

Comme la lecture de tutoriels et de posts sur le sujet, je m'adresse
a vous pour que vous m'aidiez, en fait je voudrais générer des
nombres aleatoires compris entre 10000 et 99999 inclus.


Avec Boost.Random, en modifiant legerement l'exemple qui est au
debut de la documentation:

// generateur pseudo-aleatoire
boost::mt19937 rng;
// loi uniforme entre 10000 et 99999
boost::uniform_int<> dist(10000, 99999 );
// objet fonctionnel associant le generateur et la loi
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
die(rng, dist);
int x = die();

Tu peux choisir une autre loi, et aussi un autre generateur.

Si ton compilateur supporte le TR1 , tu dois retrouver la meme chose
dans <random>.

Avatar
Sylvain
Leo wrote on 06/02/2007 21:03:

Comme la lecture de tutoriels et de posts sur le sujet,


?! fait défaut ?, est confuse ?, ...

je m'adresse a vous pour que vous m'aidiez, en fait
je voudrais générer des nombres aleatoires


pseudo-aléatoire, même très très pseudo avec rand ...

compris entre 10000 et 99999 inclus.
et : int variable = (int)(rand() / (double)RAND_MAX * (N - 1));
avec RAND_MAX = 100000
et N = 10000


RAND_MAX est défini dans stdlib.h et comme indiqué par James parfois
défini à 0x7FFF mais cela peut être bcp plus.
avez-vous regardé la doc de votre librairie standard ? quelle est la
taille de vos "int" ? rand date d'une époque où les int pouvait faire 16
bits, si vous avez un rand en 64 bits et divisez par un RAND_MAX
redéfini à 100000 cela fera en effet des nombres supérieurs à 99999.

si de plus vous voulez une borne inférieure != de 0, il faudra surement
quelque chose comme: nb = lowerBnds + random() ou plus précisemment:

int nb = min + ((randomInt() % (max - min));


avec un randomInt() qui retournera des nb entre 0 et "MAX_SIGNED_INT".

Sylvain.

Avatar
Leo
On 7 fév, 12:30, Michel Decima wrote:

Bonjour,

Comme la lecture de tutoriels et de posts sur le sujet, je m'adresse
a vous pour que vous m'aidiez, en fait je voudrais générer des
nombres aleatoires compris entre 10000 et 99999 inclus.


Avec Boost.Random, en modifiant legerement l'exemple qui est au
debut de la documentation:

// generateur pseudo-aleatoire
boost::mt19937 rng;
// loi uniforme entre 10000 et 99999
boost::uniform_int<> dist(10000, 99999 );
// objet fonctionnel associant le generateur et la loi
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
die(rng, dist);
int x = die();

Tu peux choisir une autre loi, et aussi un autre generateur.

Si ton compilateur supporte le TR1 , tu dois retrouver la meme chose
dans <random>.


Merci, mais le problème est que cela génère qu'un seul nombre par
compilation. Saurais-tu comment faire varier les nombre ainsi
générés ?

Merci.


Avatar
Michel Decima
On 7 fév, 12:30, Michel Decima wrote:

// generateur pseudo-aleatoire
boost::mt19937 rng;
// loi uniforme entre 10000 et 99999
boost::uniform_int<> dist(10000, 99999 );
// objet fonctionnel associant le generateur et la loi
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
die(rng, dist);
int x = die();

Tu peux choisir une autre loi, et aussi un autre generateur.

Si ton compilateur supporte le TR1 , tu dois retrouver la meme chose
dans <random>.


Merci, mais le problème est que cela génère qu'un seul nombre par
compilation. Saurais-tu comment faire varier les nombre ainsi
générés ?


Tu veux dire que la valeur de x est toujours la meme pour chaque
execution du code, et tu voudrais qu'elle change a chaque fois,
donc l'equivalent de l'appel a srand dans le code d'origine ?

Pour faire ca, tu peux utiliser le constructeur du generateur,
ou bien sa fonction membre seed() :

int seedValue = time( NULL );
boost::mt19937 rng( seed );
// loi uniforme entre 10000 et 99999
boost::uniform_int<> dist(10000, 99999 );
// objet fonctionnel associant le generateur et la loi
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
die(rng, dist);

for (int i=0; i< 10; ++i) std::cout << die() << "n";
std::cout << std::endl;
rng.seed( seedValue );
for (int i=0; i< 10; ++i) std::cout << die() << "n";
std::cout << std::endl;

(code pas teste, mais ca dois marcher).

Ca doit de donner deux sequences identiques par appel, et elles
seront differentes entre deux appels (sauf bien sur si trop
rapproches).


Avatar
Leo
On 8 fév, 16:49, Michel Decima wrote:



On 7 fév, 12:30, Michel Decima wrote:

// generateur pseudo-aleatoire
boost::mt19937 rng;
// loi uniforme entre 10000 et 99999
boost::uniform_int<> dist(10000, 99999 );
// objet fonctionnel associant le generateur et la loi
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
die(rng, dist);
int x = die();

Tu peux choisir une autre loi, et aussi un autre generateur.

Si ton compilateur supporte le TR1 , tu dois retrouver la meme chose
dans <random>.


Merci, mais le problème est que cela génère qu'un seul nombre par
compilation. Saurais-tu comment faire varier les nombre ainsi
générés ?


Tu veux dire que la valeur de x est toujours la meme pour chaque
execution du code, et tu voudrais qu'elle change a chaque fois,
donc l'equivalent de l'appel a srand dans le code d'origine ?

Pour faire ca, tu peux utiliser le constructeur du generateur,
ou bien sa fonction membre seed() :

int seedValue = time( NULL );
boost::mt19937 rng( seed );
// loi uniforme entre 10000 et 99999
boost::uniform_int<> dist(10000, 99999 );
// objet fonctionnel associant le generateur et la loi
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
die(rng, dist);

for (int i=0; i< 10; ++i) std::cout << die() << "n";
std::cout << std::endl;
rng.seed( seedValue );
for (int i=0; i< 10; ++i) std::cout << die() << "n";
std::cout << std::endl;

(code pas teste, mais ca dois marcher).

Ca doit de donner deux sequences identiques par appel, et elles
seront differentes entre deux appels (sauf bien sur si trop
rapproches).


Merci beaucoup.



Avatar
Olivier Miakinen

[...] j'utilise normalement quelque chose du genre :

int const limit = RAND_MAX - RAND_MAX % N ;
int result = rand() ;
while ( result >= limit ) {
result = rand() ;
}


Pas bête ! Ta constante limit est ainsi la plus grande valeur inférieure
ou égale à RAND_MAX telle que (limit % N == 0). Comme elle vaut au moins
RAND_MAX/2, la boucle while() ne tournera jamais trop longtemps (ou
alors ce serait vraiment pas de chance).

Avatar
James Kanze
Olivier Miakinen wrote:

[...] j'utilise normalement quelque chose du genre :

int const limit = RAND_MAX - RAND_MAX % N ;
int result = rand() ;
while ( result >= limit ) {
result = rand() ;
}


Pas bête ! Ta constante limit est ainsi la plus grande valeur inférie ure
ou égale à RAND_MAX telle que (limit % N == 0). Comme elle vaut a u moins
RAND_MAX/2, la boucle while() ne tournera jamais trop longtemps (ou
alors ce serait vraiment pas de chance).


Ou que j'ai un mauvais générateur aléatoire. (Mais
statistiquement, c'est bon:-).)

L'importance, ici, c'est qu'on se rend compte qu'il faut ôter
certaines valeurs de retour, impérativement, puisqu'il faut que
le nombre total des valeurs de rétour possible soit un multiple
de limit. Sinon, la probabilité ne peut pas être identique pour
chacune des valeurs.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Olivier Miakinen

[...]

L'importance, ici, c'est qu'on se rend compte qu'il faut ôter
certaines valeurs de retour, impérativement, puisqu'il faut que
le nombre total des valeurs de rétour possible soit un multiple
de limit.


Le lecteur aura rectifié de lui-même : un multiple de N.

Sinon, la probabilité ne peut pas être identique pour chacune
des valeurs.


Toutafé.

Avatar
Michel Decima
[...]

L'importance, ici, c'est qu'on se rend compte qu'il faut ôter
certaines valeurs de retour, impérativement, puisqu'il faut que
le nombre total des valeurs de rétour possible soit un multiple
de limit.


Le lecteur aura rectifié de lui-même : un multiple de N.

Sinon, la probabilité ne peut pas être identique pour chacune
des valeurs.


Toutafé.


Et c'est aussi pour ca que j'aime bien la solution Boost/TR1 : en
lisant uniform_int<>, je sais quelle distribution on utilise, je
n'ai pas besoin de le deduire du code (et c'est surement moins
trivial pour d'autres distributions).