Notes sur le langage C
Date de publication : 29 avril 2009
XXXV. <time.h> : La gestion du temps
XXXVI. <time.h> : bien utiliser difftime()
XXXVII. rand(), srand()... j'y comprends rien...
XXXV. <time.h> : La gestion du temps
XXXVI. <time.h> : bien utiliser difftime()
Les fonctions de <time.h> offrent une interface assez complexe. Voici un exemple qui rassemble
l'usage de la plupart de ces fonctions.
# include <stdlib.h>
# include <stdio.h>
# include <time.h>
int main (void )
{
time_t now = time (NULL );
struct tm tm_now = * localtime (& now);
char s[64 ];
strftime (s, sizeof s, " %d/%m/%Y " , & tm_now);
printf (" Aujourd'hui : %s\n " , s);
{
struct tm tm_xmas =
{ 0 } ;
tm_xmas.tm_year = tm_now.tm_year;
tm_xmas.tm_mon = 12 - 1 ;
tm_xmas.tm_mday = 25 ;
{
time_t xmas = mktime (& tm_xmas);
strftime (s, sizeof s, " %d/%m/%Y " , & tm_xmas);
printf (" Noel : %s\n " , s);
{
time_t diff = difftime (xmas, now);
struct tm tm_diff = * gmtime (& diff);
printf (" Plus que %d jours avant Noel\n " , tm_diff.tm_yday);
}
}
}
return 0 ;
}
|
XXXVII. rand(), srand()... j'y comprends rien...
Un générateur pseudo-aléatoire est une machine qui génère une séquence de nombres déterminée, cyclique,
mais difficile à prévoir pour un humain. De plus, la répartition des valeurs (histogramme) est supposée
être équilibrée.
La génération n'est pas 'spontanée', mais 'à la demande' (par appel de la fonction rand()). Les valeurs
produites sont comprises entre 0 et RAND_MAX inclus.
A chaque fois que l'on appelle rand(), une nouvelle valeur sort :
# include <stdio.h>
# include <stdlib.h>
int main (void )
{
int i;
printf (" Les valeurs vont de 0 a %d\n " , RAND_MAX);
for (i = 0 ; i < 10 ; i+ + )
{
int val = rand ();
printf (" %d " , val);
}
printf (" \n " );
return 0 ;
}
|
Par exemple :
Les valeurs vont de 0 à 32767
41 18467 6334 26500 19169 15724 11478 29358 26962 24464
|
Mais on constate que si on lance le programme plusieurs fois, la séquence est toujours la même.
On peut modifier l'origine de la séquence avec srand(), en passant une valeur comprise entre 0 et RAND_MAX.
Par exemple 10 :
# include <stdio.h>
# include <stdlib.h>
int main (void )
{
int i;
srand (10 );
printf (" Les valeurs vont de 0 a %d\n " , RAND_MAX);
for (i = 0 ; i < 10 ; i+ + )
{
int val = rand ();
printf (" %d " , val);
}
printf (" \n " );
return 0 ;
}
|
On constate que les valeurs sont différentes du tirage précédent, mais que si on relance le programme,
elles restent identiques :
Les valeurs vont de 0 à 32767
71 16899 3272 13694 13697 18296 6722 3012 11726 1899
|
Pour avoir une séquence différente à chaque lancement du programme, il faut donc trouver un moyen de
passer une valeur 'changeante' à srand(), d'où l'idée d'utiliser la valeur retournée par time(),
qui change une fois par seconde, indépendamment du programme (c'est une valeur gérée par le système).
Une seconde, c'est long, mais ça suffit pour les besoins courants.
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
int main (void )
{
int i;
srand ((unsigned ) time (NULL ));
printf (" Les valeurs vont de 0 a %d\n " , RAND_MAX);
for (i = 0 ; i < 10 ; i+ + )
{
int val = rand ();
printf (" %d " , val);
}
printf (" \n " );
return 0 ;
}
|
Si on lance plusieurs fois le programme (au moins une seconde entre chaque lancement), on obtient maintenant
des séquences différentes :
25985 16903 23861 29724 17917 23752 17039 25712 20507 30816
26197 27421 5384 20976 236 16846 22741 32047 12417 24408
26433 14874 13653 16830 21990 4658 17461 17892 21603 7731
|
etc. Je précise que pour que les valeurs changent dans le programme, il faut évidemment que srand()
ne soit appelé qu'une seule fois au début du programme.
Après, il y a des astuces arithmétiques pour réduire la plage de valeurs... C'est du bête calcul entier...
Détails dans la FAQ de f.c.l.c., notamment
ici.
D'autre part,
ceci peut aider.
Copyright © 2009 Emmanuel Delahaye.
Aucune reproduction, même partielle, ne peut être faite
de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.