Tous | Basic Casio | C/C++/ASM | LuaFX | Graphisme | Transferts | Logiciels | Diverses astuces

Calculatrice
Toutes
Graphs 35 à 100
Graph 25
Graphs 75/85/95 (SD)
Graph 100(+)
Classpad 300/330 (+)
Fx-CG 10/20
Fx-CP 400
Graph 90+E

Retour à la liste des tutoriels
Tutoriel Casio : Maitrisez l'aléatoire avec rand()
Tutoriel rédigé le : 2014-02-27 20:36  par Dark storm  Catégorie : C/C++/ASM  Calculatrice : Graphs 75/85/95 (SD)

Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (54 commentaires)

Maitrisez l'aléatoire avec rand()
Besoin d'un peu d'aléatoire dans tes programmes C/C++ ? Ce tuto est fait pour toi !


Prérequis :

Tout d'abord, la génération de nombres aléatoires de manière "classique" en C/C++ repose sur les fonctions rand() et srand(). Celles-ci sont incluses dans la bibliothèque stdlib.h, il sera donc nécessaire de l'inclure dans le header de notre projet.


Générer des nombres aléatoires :

Pour générer un nombre aléatoire, le microprocesseur est incapable d'en déterminer un lui même. Il faut l'aider un peu, et c'est ce que l'on a fait en rentrant dans la calculatrice une fonction de ce type :

static unsigned int lastrandom=0x12345678;

unsigned int random(int seed = 0)
{
        if(seed) lastrandom = seed;
        lastrandom = ( 0x41C64E6D * lastrandom ) + 0x3039;
        return (lastrandom >> 16);
}


Bref, lors de son premier appel, la fonction rand() retournera alors le nombre de seed 0, puis celui dont le seed est la dernière valeur générée. On aura donc, par exemple
-> 0x 52 07 EB F8
-> 0x 72 65 C8 62
-> Etc.

Le problème, c'est que du coup, à chaque lancement du programme on aura les mêmes valeurs, puisque le seed original est le même...

Pour palier à cela, on détermine plus ou moins aléatoirement le seed avant le premier appel de la fonction avec srand(int position). On ne l'utilisera qu'une seule fois, au tout début du programme.

Le plus dur dans tout ça, c'est de trouver un nombre qui soit suffisamment "aléatoire" pour qu'il soit différent à chaque fois. Pour cela, nous allons utiliser le syscall RTC_getTicks().

RTC_getTicks() est une fonction très pratique qui retourne le nombre de ticks, c'est à dire de fractions (1/128) de seconde qui se sont écoulés depuis une certaine date (inconnue). Autant dire que la probabilité que le programme soit lancé deux fois en 1/128 seconde est minimale.

Voici le code à inclure :
static int SysCallCode[] = {0xD201422B,0x60F20000,0x80010070};
static int (*SysCall)(int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallCode;

int RTC_getTicks()
{
     return (*SysCall)(0, 0, 0, 0, 0x3B);
}


Pour résumer, générer un nombre aléatoire se fait de cette façon :
1) On initialise avec srand(RTC_getTicks());
2) On récupère le nombre avec rand() : int nbAlea = rand();


Traitement du nombre aléatoire :

C'est bien joli, mais rand() ne retourne qu'un nombre compris entre 0 et 2^32-1 = 4294967295. Et nous voudrions un nombre entier entre 0 et 10, par exemple. C'est pour cela que nous allons modifier ce nombre :

Nombre entier entre 0 et max :
Nous allons utiliser le modulo (%), opération très pratique qui retourne le résultat de la division euclidienne de a par b (a%b). Or, puisque que ce reste n'est jamais supérieur à b, il est forcément égal à 0, 1, 2, 3, ..., b-1. Nous pouvons donc faire, pour générer un nombre entre 0 (inclus) et max (exclus) :
int rand_int(int max)
{
    return rand() % max;
}


Nombre entier entre min et max :
Toujours en utilisant le modulo, il est possible de bidouiller la fonction ci-dessus pour inclure le fait d'avoir un minimum :
int rand_int_ab(int min, int max)
{
    return rand() % (max - min) + min;
}

On a donc un nombre entier aléatoire entre min (inclus) et max (exclus).

Nombre décimal entre min et max :
Le problème du modulo, c'est qu'il ne permet que de travailler sur des entiers. Nous allons donc devoir nous en passer pour la génération de nombre décimaux (sous forme de float).
Nous avons vu que rand() retournait un nombre entre 0 et 2^32. Donc en supposant que RAND_MAX = 2^32, rand() / RAND_MAX est compris entre 0 et 1. Sachant que RAND_MAX est déjà défini dans "time.h", on peut l'utiliser tel quel. On en déduit alors la fonction suivante :
float rand_float_ab(float min, float max)
{
    return ( rand() / RAND_MAX ) * (max - min) + min;
}



Conclusion et annexes :

Ce tuto touche à son terme, j'espère qu'il t'aura été utile, et que tu as compris les bases de la fonction rand().
Si toutefois tu souhaite plus d'informations, ou que tu as une question, n'hésite-pas à laisser un commentaire ci-dessous !

De plus, tu trouvera peut-être ton bonheur sur l'ancien Site du Zéro, et plus particulièrement ici.


A bientôt sur Planète Casio !


Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (54 commentaires)

Publicité et partenaires
Casio Education
Casio éducation

TI-Planet
Casiopeia
Casiopeia
CasioFan, la communauté ClassPad
CasioFan
CodeWalrus
CodeWalrus

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2017 | Il y a 39 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Rugby Manager | Jeu de basket | Jeu de handball | Jeu de tennis | Nova Raider | Réparation téléphone | Soccer Rush | Tasty Tale

Planète Casio est un site communautaire indépendant, géré bénévolement et n'est donc pas affilié à Casio | Toute reproduction de Planète Casio, même partielle, est interdite
Les fichiers, programmes et autres publications présents sur Planète Casio restent la propriété de leurs auteurs respectifs et peuvent être soumis à des licences ou des copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd