Fonction c

Résolu
ahmoude Messages postés 3 Date d'inscription   Statut Membre Dernière intervention   -  
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   - 15 déc. 2007 à 00:03
Bonjour,
comment faire une fonction qui me donne un nombre aleatoire entre par exemple 3 et 20
A voir également:

9 réponses

mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
comme ça:
int aleat()
{
    int nb;
    srand(time(NULL));
    nb=(rand()%18)+3;
return nb;
}
0
baladur13 Messages postés 47653 Date d'inscription   Statut Modérateur Dernière intervention   13 655
 
Bonsoir Ahmoude
Ou encore comme ceci
https://nicolasj.developpez.com/articles/libc/hasard/
Salut
0
Qwerti Messages postés 166 Date d'inscription   Statut Membre Dernière intervention   85
 
Salut,

la technique de Mype n'est pas la meilleure car tu n'obtiendras pas des nombres pseudo-aleatoires satisfaisants... d'ailleurs les nombres aleatoires des bibliotheques C/C++ sont pas top en général... En plus il faut initialiser le generateur EN DEHORS de l'appel de la fontion sinon tu obtiendras toujours le meme nombre... :/

Je conseille plutot ceci :


#include <stdlib.h> // <--- contient les fonctions srand() et rand()
#include <time.h> // <--- contient la fonction time()
#include <stdio.h> // <--- pour utiliser printf() :-D


int initaleat() {
srand( time(NULL) ); // Ceci initialise le générateur de nbres pseudo-aléatoires
}

int aleat() {
int nb;
nb = ( (rand() * 18 ) / RAND_MAX ) + 3 ;
return nb ;
}

int main() {
initaleat();

// Ici tes appels a la fonction aleat, genre :

printf("%d",aleat());
}






a+
-Qwerti.
0
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
c'est exactement ce que j'ai fait avec deux fois moins de ligne de code...
et comme il n'a besoin que d'un seul nombre aleatoire au peut initialiser a l'interieur de la fonction sa change rien
0
Qwerti Messages postés 166 Date d'inscription   Statut Membre Dernière intervention   85
 
Salut Mype,

Désolé si j'ai eu l'air de déprecier ce que tu as écrit, ce n'était pas du tout mon but !

Cependant :

Pour l'initialisation j'aime mieux qu'elle soit ailleurs que dans la fonction aleat() elle-meme, juste au cas ou l'on décide au dernier moment de tirer 2 nombres aléatoires au lieu d'un... ca peut arriver :-D

Il y a une différence avec ce que tu as fait : je n'ai pas utilisé l'operateur modulo ( % ). Il se trouve qu'on obtient une distribution désastreuse si l'on s'en sert...

a+
-Qwerti.
0
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
Il y a une différence avec ce que tu as fait : je n'ai pas utilisé l'operateur modulo ( % ). Il se trouve qu'on obtient une distribution désastreuse si l'on s'en sert...
que veux tu dire par la ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Qwerti Messages postés 166 Date d'inscription   Statut Membre Dernière intervention   85
 
Mype,

Un exemple simple (pas tres realiste mais bon...)

Imagine tu as un generateur de nombres pseudo-aleatoires rand() qui donne des nombres entre 0 et 18.

Si tu fais

nb = ( rand() % 18 + 3 );

il est clair que 3 va arriver avec la probabilité 2/19 et les autres nombres entre 4 et 20 avec la probabilité 1/19, ce qui n'est pas top d'un point de vue equidistribution.

Autre chose que D. Knuth souleve dans son bouquin "The Art Of Computer Programmming vol. 2" (excellent chapitre sur les nombres aleatoires !!! un must !) : les LSB ne sont pas bien distribués...

Pour une "bonne" distribution, le mieux est de "normaliser" les nombres entre 0 et 1 comme ca :

rand() / RAND_MAX ;

( RAND_MAX est la valeur max prise par la fonction rand() )

puis de multiplier par l'amplitude souhaitée (ici 18) puis faire le décalage (3 dans notre exemple).

J'espere que je suis pas trop confus dans mes explications.

a+
-Qwerti.
0
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
il est clair que 3 va arriver avec la probabilité 2/19 et les autres nombres entre 4 et 20 avec la probabilité 1/19, ce qui n'est pas top d'un point de vue equidistribution.

pas du tout les nombres ont la meme probabilite dans ce cas
car (rand() % 18) tire un nombre entre 0 et 18 et ensuite on ajoute 3
ce qui fait si le nombre tiré est 0 on a 3
si le nombre tiré est 3 on a 6
donc tous les nombre entre 3 et 20 ont la meme probabilité d'etre (1/19) ( c'est tjr ce qu'on m'a appris...)

mais peu etre que tu as raison... ;)

mais bon je critique pas ta solution non plus elle est juste c'est juste que je la trouve un peu trop longue surtout pr un debutant et le principale peu importe la metjode c'est qu'il a resolu son probleme ;)
0
Qwerti Messages postés 166 Date d'inscription   Statut Membre Dernière intervention   85
 
Attention je pense qu'il y a un bug dans ton raisonnement Mype !

Reprend mon exemple :

Imagine rand() ne tire que des nombres (entiers) entre 0 et 18 (inclus).

Ainsi, chaque entiers entre 0 et 18 a un probabilité de 1/19 (il y 19 nombres, qu'on suppose equidistribués).

Maintenant,

nb = rand() % 18 ;

est un nombre entre 0 et 17 (inclus) et ca marche comme ca :

Si rand() == 0, alors nb = 0 ;
Si rand() == 1, alors nb = 1 ;
Si rand() == 2, alors nb = 2 ;
etc...
Si rand() == 17, alors nb = 17;
Enfin, si rand() == 18, alors nb = 0 ; // (car 18 % 18 = 0).

J'espere que la c'est clair que nb == 0 sort avec la probabilité 2/19 (car on obtient 0 de 2 manieres differentes : lorsque rand() == 0 et lorsque rand() == 18, chacun ont la proba 1/19 donc la proba de nb == 0 est 1/19+1/19 = 2/19). Par contre, tous les autres entiers sortent avec la proba 1/19.

Est-ce clair ? :/

a+
-Qwerti.
0
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
mais rand() ne s'arrete pas a 18 il vas jusqu'a RANDMAX
ce qui fait qu'il n'y pas que 0 qui se repete mais tous les nombres jusqu'a 17 se repete plusieurs fois
donc tu a toute une liste de nombres comme ça
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 0 1 2...17 0 1 2... 17
et ensuite un nb est tiré au hasard parmis cette liste et ds cette liste 0 se repete autant de fois que 4 ou 17 ou n'importe qu'elle nombre
il y a donc bien une equiprobabilité
0
Qwerti Messages postés 166 Date d'inscription   Statut Membre Dernière intervention   85
 
Oui oui oui mype, je sais bien que rand() ne s'arrete pas a 18, mais dans mon exemple j'ai justement supposé que RAND_MAX = 18 :-)

Mais le coup du "modulo" ( % ) c'est pas top aussi a cause du fait que les chiffres les moins significatifs ne sont pas bien distribués (et tu utilises justement les chiffres les moins significatifs en utilisant l'operateur "modulo" ( % ) ). Par contre, faire :

int nb = rand() / RAND_MAX * 18 ;

ca utilise les chiffres les plus significatifs qui sont mieux distribues.

Je te conseille tres vivement la lecture de "The Art of Computer Programming vol. 2" de Donald KNUTH.

a+
-Qwerti.

PS. Quand tu dis que dans la liste 0 1 2 etc... 0 se repete autant de fois que les autres chiffres, ce n'est vrai que si (RAND_MAX+1) est divisible par 18. Sinon il y a un difference de 1/(RAND_MAX+1) entre certaines probabilites. Cest exactement ce que mon exemple illustre. Mais bon, je chipotte vraiment, car en general RAND_MAX est grand, et du coup 1/(RAND_MAX+1) est petit, et on peu vraiment le négliger. Lis le chapitre de KNUTH sur les nombres pseudo-aleatoires (un bouquin ionant !) et il explique pourquoi les LSB ne sont pas tres bien distribues et donc pourquoi ce n'est pas toujours bien d'utiliser %.
0
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
voila exactement RANDMAX est tellement enorme qu'on peut negliger c'est ce que je voulais dire
on peut dire que c'est quasiment equiprobable ;)
0
Qwerti Messages postés 166 Date d'inscription   Statut Membre Dernière intervention   85
 
Ok mype, la tu gagnes :-D

Mais jette un coup d'oeil sur le bouquin sus-cité.

a+ et bonne soirée
-Qwerti.
0
mype Messages postés 2435 Date d'inscription   Statut Membre Dernière intervention   436
 
ok j'irais voir ça
c'est toujours interressant d'apprendre de nouvelle choses
0