|
L'équipe progG de Ti-Fr
|
Voici les nicks de vos serviteurs ;-)
chickensaver_john
Kevin Kofler
Thibaut
janjan2
TiMad
Iceman89
fréka
Zewoo
Squale92
Verstand
ZdRUbAl
UtOpIaH
et nEUrOne ...
|
|
Une idée ?
|
Une idée pour améliorez cette partie?
ou tout simplement vous souhaitez participer à l'élaborations
des tutos.
Mailez-nous ici
|
| |
Chapitre
XVII
Ce Chapitre va nous permettre de voir les manipulations de
base permettant de créer des programmes de mathématiques sur la TI, en C.
Pour cela, les instructions nouvelles que nous utiliseront proviennent (en
particulier) des librairies <timaths.h>
et <estack.h>.
En effet, la librairie <timaths.h>
contient de nombreuse fonctions de manipulation de floats
(nombres en virgule flottante), et la librairie <estack.h>
contient de nombreuses fonctions permettant de faire du calcul symbolique, avec
un peu d'entraînement...
Avant que vous ne vous attaquiez à ce chapitre, je tiens
à préciser une chose : le TI-BASIC est parfaitement adapté aux
manipulations mathématiques... en effet, même si écrire des programmes de
mathématiques en C vous permettra de gagner un peu de temps (sur la
vitesse d'exécution du programme), vous perdrez beaucoup de mémoire sur la TI
!!!.
De plus, il est beaucoup plus simple de créer des programmes
de maths en TI-BASIC qu'en C, puisque vous utilisez en permanence
les instructions TI-BASIC lorsque vous travaillez...
Donc, à mon avis, l'utilisation du C pour faire des
programmes de Mathématique doit plus être vue comme un "défi" que
comme d'une réelle utilité...
I:\ Avant
propos :
Pour pouvoir utiliser des fonctions mathématiques en C
sur une expression, il est utile que celle-ci soit localisée sur le Stack, ou,
du moins, qu'elle puisse être repérée par un pointeur de type ESI
(Expression Stack Index), qui permet de pointer (comme son nom l'indique !) vers
un emplacement sur le Stack. En effet, la plupart des fonctions qui vous
permettront de travailler en maths en C passent par le Stack...
La façon la plus simple d'obtenir l'expression sur laquelle
vous souhaitez travailler sur le Stack et de la donner en Argument au programme
: il vous faudra ensuite le lancer de la façon suivante à partir de l'écran
HOME de votre TI :
progr(expression_a_etudier)
A présent, il vous est possible de récupérer cet argument
de a façon suivante (en fait, cela fonctionne de la même façon que pour les
Chaînes de caractères, Cf Chapitre
VII, mais, ici, il s'agit d'expressions).
Vous pouvez commencer par vérifier qu'un argument a bien
été fourni au programme à son lancement... Pour cela, utilisez ceci :
if(ArgCount()!=1)
{
DlgMessage("Erreur...","Vous
devez mettre la fonction en argument !",BT_OK,BT_NONE);
return;
}
De la sorte, si vous ne lancez pas le programme en
lui fournissant un argument, vous aurez un message qui sera affiché dans une
boîte de Dialogue, et le programme se terminera.
L'argument que vous avez passé au programme est
maintenant localisé au niveau du top_estack,
c'est-à-dire au sommet du Stack, puisque c'est la dernière valeur qui lui a
été envoyée.
Pour le récupérer, et même le mémoriser, il vous faudra
utiliser ceci :
ESI
a_etudier;
a_etudier = top_estack;
A présent, la variable a_etudier contient l'argument
que vous aviez passé au programme. Il vous sera maintenant possible de
travailler avec cette variable.
Si vous souhaitez créer un programme admettant plusieurs
arguments, sachez que le dernier argument entré est celui qui sera localisé le
plus haut sur le Stack : si, au lancement du programme, vous effectuez ceci : prog(Arg1,
Arg2, Arg3), souvenez vous que top_estack
pointera vers Arg3. Il vous faudra ensuite utiliser la fonction suivante pour à
chaque fois accéder à l'argument passé au rang précédent :
next_expression_index(pointeur_de_type_ESI);
Cette fonction renvoie un pointeur de type ESI
vers l'argument qui avait été passé au programme avant celui qui est donné
en argument de la fonction. Ainsi, par appels successifs à cette fonction, il
serait possible de remonter sur TOUT le Stack.
Attention : si vous atteignez le premier argument passé au
programme, le résultat suivant sera une erreur. En effet, le premier argument
passé au programme (qui sera localisé en dernière position sur le Stack sera
suivi sur celui-ci d'un END_TAG, qui
entraînera une erreur avec cette fonction. Je vous conseille donc de ne créer
que des programmes admettant un nombre constant d'arguments, que vous pourrez
vérifier !)
II:\
Affichage de données localisées sur le Stack, en Pretty
Print :
Il est possible, à partir d'un programme en C, de
présenter des résultats de la même façon que dans l'écran HOME, en Pretty
Print (ou Écriture bidimensionnelle).
Pour cela, il faut utiliser les fonctions suivantes :
Tout d'abord, pour organiser ce qu'il faudra afficher, il
convient d'utiliser la fonction ayant cette syntaxe :
Parse2DExpr(resultat_ESI, FALSE);
Cette fonction renvoie un pointeur de type ESI vers ce
qu'il faudra ensuite afficher : elle permet d'organiser les données pointées
par l'argument resultat_ESI (qui correspond à un pointeur de type ESI),
afin qu'elles puissent être affichée avec la fonction que nous verrons juste
après.
Le premier argument qu'il convient de passer à cette
fonction est un pointeur de type ESI,
qui désigne ce que nous voudrons afficher (par exemple, le résultat d'un
calcul). Je ne sais pas exactement à quoi correspond le second argument, mais,
à chaque fois que j'ai utilisé cette fonction, j'ai passé FALSE,
et le résultat obtenu à été celui que j'attendais.
Nous utiliserons dorénavant cette fonction de cette façon :
ESI
pour_afficher;
pour_afficher = Parse2DExpr(resultat_ESI,
FALSE);
De cette façon, le pointeur pour_afficher
correspondra à ce que nous afficherons à l'écran, pour l'instruction
suivante.
Ensuite, pour afficher ce que l'on souhaite à l'écran,
il faut utiliser cette fonction :
Print2DExpr(pour_afficher, fenetre_de_destination, x, y);
Le premier argument de cette fonction, pour_afficher,
correspond au résultat que nous avons obtenu avec la fonction précédente. Le
second, fenetre_de_destination, correspond à la fenêtre où le
résultat sera affiché (le plus simple sera souvent de prendre la fenêtre par
défaut du TIOS, qui est désignée par la constante DeskTop).
Enfin, les deux derniers arguments correspondent à la position à l'écran ou
sera affiché l'expression en Pretty Print.
Attention
: l'argument x désigne la position de l'extrémité
gauche de l'expression, mais la variable y désigne la position du centre
(en hauteur) de l'expression, et non pas son coin supérieur gauche ou droit
!!!
Étant donné qu'il peut vous être utile de connaître la
hauteur de l'expression à afficher avec la fonction précédente (puisque vous
donnez la position d'affichage de son centre), cette fonction vous sera
certainement d'un grand secours :
Parms2D(pour_afficher, &largeur,
&bas, &haut);
Le premier argument que prend cette fonction
correspond au pointeur renvoyé par l'instruction Parse2DExpr.
Ensuite, les trois arguments suivants sont de type short,
et correspondent respectivement à la larguer de l'expression (cela peut vous
être utile !), au nombre de pixels qui se situent entre son centre et son bord
inférieur, puis entre son centre et son bord supérieur.
Cette fonction doit être utilisée de la façon suivante :
// Commencez par préparer l'affichage du
résultat avec Parse2DExpr.
short
largeur=0,
bas=0,
haut=0;
// Déclaration des 3 variables concernant la
taille de l'expression à afficher.
Parms2D(pour_result,
&largeur2, &bottom2,
&top2); //
Détermination de la taille de celle-ci.
// A présent, il vous est possible
d'afficher le résultat avec la fonction Print2DExpr
Voici la fonction que j'utilise généralement pour
afficher à l'écran des résultats de calculs : (Cette fonction est loin
d'être parfaite, mais elle vous permet de faire scroller horizontalement les
résultats, ainsi que de décider de la position à laquelle vous les affichez
en hauteur...).
void fonction_affiche(ESI
affiche_result, short y_aff_result)
{
short largeur2=0,
bottom2=0,
top2=0,
x_aff=0,
key2=0,
lcd_width = LCD_WIDTH;
ESI fonction_div1 =
affiche_result, pour_result;
SCR_RECT ecran2 =
{{0, 0,
lcd_width, LCD_HEIGHT}};
pour_result = Parse2DExpr(fonction_div1,
FALSE);
Parms2D(pour_result,
&largeur2, &bottom2,
&top2);
do
{
debut:
Print2DExpr(pour_result,
DeskTop, x_aff, y_aff_result);
ST_showHelp("Pressez
une touche...");
key2 = GKeyIn(NULL,0);
FontSetSys(F_4x6);
if
(key2 == KEY_RIGHT)
{
if(lcd_width+abs(x_aff)>=largeur2
|| largeur2<=lcd_width)
{
goto
debut;
}
x_aff-=30;
}
else
if(key2==KEY_LEFT
&& x_aff<=0)
{
if(abs(x_aff)<=0)
{
goto debut;
}
x_aff+=30;
}
else
if(key2==4096+KEY_RIGHT)
{
if(lcd_width+abs(x_aff)>=largeur2
|| largeur2<=lcd_width)
{
goto
debut;
}
x_aff=0-(largeur2-lcd_width);
}
else
if(key2==4096+KEY_LEFT
&& x_aff<=0)
{
if(abs(x_aff)<=0)
{
goto debut;
}
x_aff=0;
}
else
if(key2 == KEY_DIAMOND+KEY_RIGHT)
{ //
WARNING : Comparison between signed and unsigned
if(lcd_width+abs(x_aff)>=largeur2
|| largeur2<=lcd_width)
{
goto debut;
}
x_aff-=lcd_width/3;
}
else
if(key2 == KEY_DIAMOND+KEY_LEFT
&& x_aff<=0)
{ //
WARNING : Comparison between signed and unsigned
if(abs(x_aff)<=0)
{
goto debut;
}
x_aff+=lcd_width/3;
}
if(lcd_width+abs(x_aff)
>= largeur2)
x_aff =
0-(largeur2-lcd_width);
if(x_aff
>= 0)
x_aff =
0;
if(key2!=KEY_ENTER
&& key2!=KEY_ESC)
{
char
*buffer = (char
*)malloc(BITMAP_HDR_SIZE
+ lcd_width*LCD_HEIGHT/8);
SCR_RECT
dessin = {{0,y_aff_result-top2,lcd_width,y_aff_result+bottom2}};
BitmapGet(&dessin,
buffer);
BitmapPut(0,
y_aff_result-top2, buffer,
&ecran2, A_XOR);
}
DrawLine(0,
y_aff_result-top2, 0,
y_aff_result+bottom2, A_REVERSE);
}while(key2!=KEY_ENTER
&& key2!=KEY_ESC);
}
Le premier argument que prend cette fonction
correspond à un pointeur de type ESI,
qui désigne ce que vous voudrez afficher. Le second argument que prend cette
fonction correspond à la hauteur à laquelle il faudra afficher le coin
supérieur gauche de l'expression.
Comme vous avez sans doute pu le remarquer, cette fonction
entraîne deux WARNING durant sa compilation.... Ceux-ci sont sans conséquence
néfaste !
A présent, lorsque nous voudrons afficher le résultat
d'un calcul à l'écran, nous utiliserons la notation suivante :
fonction_affiche(nom_de_l_expression_a_afficher, Y);
Et cela sera utilisé en référence à cette
fonction, pour ne pas avoir à chaque fois à réécrire une portion de code qui
l'a déjà été, dans le but de ne pas alourdir plus que nécessaire cette
page...
III:\
Logique de calcul symbolique en C, en utilisant le Stack
:
Pour ses calculs, la TI (89 et 92+) fonctionnent en RPN
(= Reverse Polish Notation, ou, en français, Notation
Polonaise Inversée). Cela signifie que, par exemple, pour
calculer l'intégrale de (1/((x-3)(x^2+4)), x),
il faudra effectuer ceci : x 1 x 3 - 2 x ^ 4 + * / Integral. (Cet exemple
provient de la doc de TIGCC, car je ne suis pas super fort en RPN !)
N'ayez crainte, vu comme cela, cela semble un peu complexe,
mais quand vous aurez vu plusieurs exemples, vous comprendrez que c'est plus
simple qu'il n'y parait !
Pour toute utilisation de calcul symbolique en C,
il sera impératif que vous connaissiez certains TAGs, définis dans la
librairie <estack.h>...
- Prenons l'exemple d'un calcul de dérivée :
- Vous avez un pointeur de type ESI,
nommée fonction_ESI, qui pointe vers l'expression dont vous
souhaitez calculer la dérivée.
- Vous savez que, en TI-BASIC, pour faire une dérivée, il vous
faut faire ceci dna sl'écran HOME : d(fonction_ESI,
x)
- Le TAG qui correspond à la fonction de dérivation est DIFFERENTIATE_TAG.
- Vous devez savoir que, pour que les calculs symboliques fonctionnent, il
vous faut en premier lieu envoyer sur le Stack un TAG nommé END_TAG,
qui marquera la fin de l'instruction. (en écriture normale, il s'agit de la
fin, et, donc, en RPN, cela sera le début !).
Pour cela, il faut utiliser l'instruction suivante :
push_END_TAG();
- Pour calculer une expression qui est localisée sur le Stack, il convient
d'utiliser cette fonction :
NG_rationalESI(top_estack);
- Ou, si vous voulez effectuer le calcul en valeur approchée :
NG_approxESI(top_estack);
- Voici donc la portion de source qui vous permet de calculer la dérivée
d'une fonction, en fonction de x :
push_END_TAG(); //
Envoie le TAG de fin d'expression.
push_quantum(VAR_X_TAG);
// Indique que la variable selon laquelle le
calcul se fera est X.
push_expr_quantum(fonction_esi,
DIFFERENTIATE_TAG); //
Envoie la fonction à dérivée, et le TAG qui permet de savoir qu'il s'agira
d'effectuer une dérivée.
NG_rationalESI(top_estack);
// Permet d'effectuer les opération données
précédemment, jusqu'à ce que END_TAG soit atteint.
// Le résultat du calcul est maintenant localisé au somment du Stack. Pour
l'afficher, il vous suffit de faire :
fonction_affiche(top_estack,
Y); //
Utilisation de la fonction d'affichage en Pretty Print définie précédemment.
IV:\
Exemples de calculs symboliques :
La meilleure façon de comprendre comment effectuer des
calculs symboliques en C est, à mon avis, d'étudier quelques exemples.
C'est donc ce que nous allons à présent faire. Les exemples pris ici
correspondent à des manipulations qu'il est fréquent de faire en TI-BASIC,
et je penses que vous les avez déjà utilisé... je n'aurai donc pas à
expliquer leur fonctionnement en TI-BASIC :-) !
Ici, dans tous les cas, nous noterons fonction_ESI le
pointeur de type ESI qui pointera vers
l'expression à étudier.
A:
Calcul de la fonction primitive d'une fonction :
push_END_TAG (); //
Envoie le TAG de fin d'expression.
push_quantum(VAR_X_TAG);
// Permet de savoir que l'étude est faite en
fonction de X.
push_expr_quantum (fonction_esi,
INTEGRATE_TAG); //
Il s'agit de faire l'intégrale de la fonction_ESI.
NG_rationalESI(top_estack);
// Fait le calcul en valeur exacte.
fonction_affiche(top_estack,
Y); //
Affiche le résultat grâce à la fonction définie précédemment.
B:
Calcul des solutions d'une fonction (Fonction Solve
en TI-BASIC) :
ESI fonction_divers;
// Déclare un autre pointeur de type ESI.
push_END_TAG(); //
Envoie le TAG de fin d'expression.
push_quantum(VAR_X_TAG);
// Permet de savoir que l'étude est faite en
fonction de X.
push_Float(0);
// On veut résoudre l'équation fonction_ESI=0.
push_expr_quantum(fonction_esi,
EQ_TAG); //
On envoie la fonction_ESI sur le Stack, ainsi que le TAG correspondant à
"=".
push_quantum(SOLVE_TAG);
// On envoie sur le Stack le TAG de la fonction
Solve.
fonction_divers= top_estack;
// On copie le sommet du Stack (jusqu'à END_TAG)
dans la seconde variable de type ESI
NG_rationalESI(top_estack);
// On effectue le calcul en valeur exacte.
fonction_affiche(top_estack,
Y1); //
On affiche le résultat du calcul en valeur exacte.
NG_approxESI(fonction_divers);
// On effectue le calcul en valeur approchée.
fonction_affiche(top_estack,
Y2); //
On affiche le résultat du calcul en valeur approchée.
Il est possible d'effectuer le même type de manipulations
pour toutes les opérations mathématiques du TIOS (ou du moins, pour celles que
j'ai essayé !). La seuls chose qu'il est impératif de ne pas perdre de vue est
le fait que vous devez, en C, envoyer les données sur le Stack dans l'ordre
inverse de celui correspondant au TI-BASIC.
Maintenant que vous avez étudié ce Chapitre, et avant de
vous mettre à programmer en C pour faire des programmes de Mathématique,
demandez-vous si vous n'y arriverez pas mieux en TI-BASIC... Ce sera
moins difficile, cela prendra moins d'espace mémoire, cela ne sera quasiment
pas plus lent, et cela sera certainement plus rapide et plus simple à programmer
!!!
Retour au menu général
Chapitre
XVIII
|
|