Fonction c

Résolu/Fermé
ahmoude Messages postés 3 Date d'inscription vendredi 14 décembre 2007 Statut Membre Dernière intervention 14 décembre 2007 - 14 déc. 2007 à 21:05
mype Messages postés 2435 Date d'inscription jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 - 15 déc. 2007 à 00:03
Bonjour,
comment faire une fonction qui me donne un nombre aleatoire entre par exemple 3 et 20

9 réponses

mype Messages postés 2435 Date d'inscription jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
14 déc. 2007 à 21:11
comme ça:
int aleat()
{
    int nb;
    srand(time(NULL));
    nb=(rand()%18)+3;
return nb;
}
0
baladur13 Messages postés 46963 Date d'inscription mercredi 11 avril 2007 Statut Modérateur Dernière intervention 29 novembre 2024 13 469
14 déc. 2007 à 21:16
Bonsoir Ahmoude
Ou encore comme ceci
https://nicolasj.developpez.com/articles/libc/hasard/
Salut
0
Qwerti Messages postés 166 Date d'inscription dimanche 2 septembre 2007 Statut Membre Dernière intervention 28 octobre 2008 85
14 déc. 2007 à 21:47
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 jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
14 déc. 2007 à 21:54
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 dimanche 2 septembre 2007 Statut Membre Dernière intervention 28 octobre 2008 85
14 déc. 2007 à 22:10
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 jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
14 déc. 2007 à 22:19
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 dimanche 2 septembre 2007 Statut Membre Dernière intervention 28 octobre 2008 85
14 déc. 2007 à 22:31
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 jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
14 déc. 2007 à 22:44
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 dimanche 2 septembre 2007 Statut Membre Dernière intervention 28 octobre 2008 85
14 déc. 2007 à 22:57
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 jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
14 déc. 2007 à 23:08
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 dimanche 2 septembre 2007 Statut Membre Dernière intervention 28 octobre 2008 85
14 déc. 2007 à 23:22
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 passionant !) 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 jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
14 déc. 2007 à 23:38
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 dimanche 2 septembre 2007 Statut Membre Dernière intervention 28 octobre 2008 85
14 déc. 2007 à 23:59
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 jeudi 1 novembre 2007 Statut Membre Dernière intervention 16 août 2010 436
15 déc. 2007 à 00:03
ok j'irais voir ça
c'est toujours interressant d'apprendre de nouvelle choses
0