Le programme Xcas
est un logiciel libre écrit en C++,
(disponible sous licence GPL). La version à jour se récupère sur :
http://www-fourier.ujf-grenoble.fr/ parisse/giac_fr.html ou
ftp://fourier.ujf-grenoble.fr/xcas
où l’on trouve le code source (giac.tgz
) ou des versions
précompilées pour Linux (PC ou ARM), Windows, Mac OS.
Xcas propose un mode de compatibilité avec Maple, MuPAD et
la TI89/92 :
pour cela, il suffit de le spécifier dans Prog style du menu de
configuration du cas (bouton Config ou menu
Cfg->Configuration du CAS) ou avec le menu
Cfg->Mode (syntax). On peut choisir, en
cliquant sur la flèche située à coté de Prog style : Xcas
ou Maple ou MuPAD ou TI89/92.
On a aussi la possibilité d’importer une session Maple
ou une archive TI89/92 en choisissant
Importer du menu Fich, ou importer dans
un niveau éditeur de programmes un fichier écrit
en syntaxe Maple, Mupad ou TI89/92
par le menu Prog->Inserer.
On présente ici le mode Xcas qui est proche de la syntaxe C. On a aussi la possibilité d’avoir toutes les instructions en français de façon à être proche du langage Algorithmique.
On édite un programme ou un script (i.e. une suite de commandes séparées
par des ;) avec son éditeur préféré : on peut écrire, dans un
même fichier, la définition de plusieurs
fonctions séparées par des points virgules (;) (que l’on
sauve par exemple sous le nom de bidon), puis dans Xcas
on tape :read("bidon"); et
cela a pour effet, de compiler les différentes fonctions de bidon,
de les mettre comme réponse (avec Success.. dans la zone des
résultats intermédiaires pour indiquer les fonctions valides).
En reéditant le programme, ou le script, avec son éditeur préféré,
on peut le corriger, le sauver sous un autre nom etc..., mais il est
préférable de le recopier dans un niveau éditeur de programmes (que l’on
ouvre avec Alt+p) pour cela on peut :
En effet, depuis un niveau éditeur de programmes, on peut :
On corrige les fautes si il y en a...
Vous sauvez le programme (ou le script) avec le bouton Save du niveau
éditeur de programmes sous le nom que vous voulez lui donner en le terminant
par le suffixe .cxx (ce nom s’inscrit alors à
côté du bouton Save du niveau éditeur de programmes). Si ensuite,
vous voulez lui donner un autre nom il faut le faire avec le menu Prog
sous-menu Sauver comme de l’éditeur de programmes.
Pour utiliser le débuggeur, il faut que ce programme soit syntaxiquement correct : vous avez par exemple un programme syntaxiquement correct, mais qui ne fait pas ce qu’il devrait faire, il faut donc le corriger.
Avec le débuggeur, on a la possibilité d’exécuter le programme au pas
à pas (sst), ou d’aller directement (cont) à une ligne
précise marquée par un point d’arrêt (break), de voir
(voir ou watch) les variables que l’on désire surveiller,
d’exécuter au pas à pas les instructions d’une fonction utilisateur utilisée dans le programme (dans ou sst_in),
ou de sortir brutalement du débuggeur (tuer ou kill).
On tape : debug(nom _du_programme(valeur_des_ arguments)).
Il faut bien sûr que le programme soit validé :
Par exemple, si pgcd a été validé, on tape :
debug(pgcd(15,25))
L’écran du débugger s’ouvre : il est formé par trois écrans séparés
par une ligne eval et une barre de boutons sst,dans,cont... :
Les commentaires sont des chaînes de caractères, ils sont précédés
de //
ou sont
parenthésés par /* */
Une action ou bloc est une séquence d’une ou plusieurs
instructions.
Quand il y a plusieurs instructions il faut les parenthéser avec { }
et séparer les instructions par un point virgule (;)
Un bloc est donc parenthésé par { } et commence
éventuellement par la déclaration des variables locales (local...).
Voir aussi 2.2
Les variables sont les endroits où l’on peut stocker des valeurs, des
nombres, des expressions, des objets.
Le nom des variables est formé par une suite de caractères et commence par
une lettre : attention on n’a pas droit aux
mots réservés ...ne pas utiliser par exemple la variable i dans un
for si vous avez coché pas de test de i dans la
configuration generale car i représente le nombre complexe de
module 1 et d’argument π/2.
L’affectation se fait avec := (par exemple a:=2; b:=a;) ou avec
=> (par exemple 2=>a; a=>b;) .
Une variable utilisée uniquement à l’intérieur d’une fonction (resp d’un
bloc) pour contenir des résultats intermédiaires est une variable
locale à la fonction (resp au bloc).
Les variables locales doivent être déclarées au début
de la fonction (resp au début d’un bloc) par le mot réservé local
puis on met les noms des variables séparés par des virgules (,).
Attention
Cette déclaration n’initialise pas ces variables locales à 0.
Les variables locales peuvent être initialisées lors de leur déclaration à une valeur en mettant les affectations entre parenthèses et separées par des virgules. Mais attention l’initialisation des variables locales faites dans la ligne de local se fait en utilisant le contexte global d’évaluation , par exemple :
n:=5; f():={ local (n:=1),(d:=n+1); return d; }
f() renvoie 6 et non 2 : c’est la valeur de n+1 ou n est global. Il faut initialiser d après la déclaration locale pour utiliser le contexte local en tapant :
f():={ local (n:=1),d; d:=n+1; return d; }
et alors f() renvoie 2.
Attention Les variables locales ne sont pas affectèes lors de leur
déclaration MAIS ce ne sont pas des variables formelles : il faut les
obligatoirement les initialiser dans le corps du programme.
Si on veut utiliser dans un programme des variables formelles, on a 2
solutions :
Il est donc préférable de définir la variable formelle var, avec
local var; suivi de assume(var,symbol); ou de purge(var).
Exemple
Voici le programme qui donne la valeur de la suite de Fibonnacci u
définie par u0=u0,u1=u1,un+2=un+1+un.
On sait que si a et b
sont les racines de x2−x−1, les suites vérifiant la relation de
récurrence un+2=un+1+un sont des combinaisons linéaires des suites
géométriques an et bn, c’est-à-dire que l’on a :
un=Aan+Bbn |
pour A et B solutions du système [u0=A+B, u1=Aa+Bb].
Voici les deux façons de faire :
u(n,uo,u1):={ local L,a,b; //verifier que A,B,x ne sont pas affect\'ees [a,b]:=solve(x^2-x-1,x); L:=linsolve([A+B=uo,A*a+B*b=u1],[A,B]); return normal(L[0]*a^n+L[1]*b^n); };Lors de la compliation, Xcas dit :
assume(A,symbol); assume(B,symbol); assume(x,symbol);ou à la commande purge(A,B,x).
Remarque : pour retrouver des variables non formelles il suffira de les
affecter.
On tape :
u(n,uo,u1):={ local L,a,b,A,B,x; assume(A,symbol); assume(B,symbol); assume(x,symbol); [a,b]:=solve(x^2-x-1,x); L:=linsolve([A+B=uo,A*a+B*b=u1],[A,B]); return normal(L[0]*a^n+L[1]*b^n); };
Ou on tape :
u(n,uo,u1):={ local L,a,b,A,B,x; purge(A,B,x); [a,b]:=solve(x^2-x-1,x); L:=linsolve([A+B=uo,A*a+B*b=u1],[A,B]); return normal(L[0]*a^n+L[1]*b^n); };
Lors de la compliation, Xcas dit :
// Success compiling u
On tape :
u(3,0,1)
On obtient :
2
Pour bien comprendre ce qui se passe, on rajoute des print :
u(n,uo,u1):={ local L,a,b,A,B,x; print(A); assume(A,symbol); print(A); assume(B,symbol); assume(x,symbol); [a,b]:=solve(x^2-x-1,x); L:=linsolve([A+B=uo,A*a+B*b=u1],[A,B]); A:=5; print(A); return normal(L[0]*a^n+L[1]*b^n); };
On tape :
A:=30
u(3,0,1)
On obtient écrit en bleu :
A:0 (A est locale et n’est pas symbolique et vaut 0)
A:A (A est locale et symbolique)
A:5 (A est locale etn’est pas symbolique et vaut 5)
puis la réponse :
2
On tape :
A
On obtient :
30 (la variable globale A n’est pas symbolique et vaut 30)
Voici comme exemple le programme de la fonction qui donne le quotient et le reste de la division euclidienne de 2 entiers (c’est la fonction iquorem de Xcas) :
idiv2(a,b):={ local (q:=0),(r:=a); if (b!=0) { q:=iquo(a,b); r:=irem(a,b); } return [q,r]; };
Voici le programme de la même fonction mais avec les variables locales internes au bloc du if :
idiv2(a,b):={ if (b==0) {return [b,a];} if (b!=0) { local q,r; q:=iquo(a,b); r:=irem(a,b); return [q,r]; } };
ou encore avec les variables locales internes au bloc du else :
idiv2(a,b):={ if (b==0) {return [b,a];} else { local q,r; q:=iquo(a,b); r:=irem(a,b); return [q,r]; } };
Les paramètres sont mis après le nom du programme ou de la fonction entre
parenthèses (par exemple f(a,b):=...).
Ces paramètres sont initialisés lors de l’appel du programme ou de la
fonction et se comportent comme des variables locales.
L’affectation se fait avec := (par exemple a:=2; b:=a;) ou se fait avec => (par exemple 2=>a; a=>b;).
Les entrées se font par passage de paramètres ou avec input.
Les sorties se font en mettant le nom de la variable à afficher (ou la
séquence des variables à afficher ou entre crochets les variables à
afficher séparées par une virgule) précedé du mot réservé
print.
Il n’y a pas de distinction entre programme et fonction : la valeur d’une
fonction est précedée du mot réservé return.
Remarque
return n’est pas obligatoire car Xcas renvoie toujours la valeur
de la dernière instruction, mais return est très utile car il fait
sortir de la fonction : les instructions situèes après return ne
sont jamais effectuées.
Avec le langage Xcas les tests ont soit une syntaxe similaire au langage
C++ soit une version française proche du langage algorithmique.
Pour les tests, les syntaxes admises sont :
testif1(a,b):={ if (a<b) b:=b-a; return [a,b]; };ou
testsi1(a,b):={ si a<b alors b:=b-a; fsi; return [a,b]; };et on a :
testif(a,b):={ if (a==10 or a<b) b:=b-a; else a:=a-b; return [a,b]; };ou
testsi(a,b):={ si a==10 or a<b alors b:=b-a; sinon a:=a-b; fsi; return [a,b]; };et on a :
Avec le langage Xcas les boucles ont soit une syntaxe similaire au
langage C++ soit une version française proche du langage
algorithmique.
La commande break permet de sortir d’une boucle.
Si vous avez fait une boucle infinie, il faut appuyer sur STOP pour
arrêter votre programme (ou sur Shift+STOP si plusieurs sessions
travaillent en parallèle).
Pour les boucles, les syntaxes admises sont :
testfor1(a,b):={ local j,s:=0; for (j:=a;j<=b;j++) s:=s+1/j^2; return s; };ou
testpour1(a,b):={ local j,s:=0; pour j de a jusque b faire s:=s+1/j^2; fpour; return s; };Si a>b, l’instruction ou le bloc d’instructions du for ou du pour ne se fera pas et la fonction retournera 0,
testfor2(a,b):={ local j,s:=0; for (j:=b;j>=a;j--) s:=s+1/j^2; return s; };ou
testpour2(a,b):={ local j,s:=0; pour j de b jusque a pas -1 faire s:=s+1/j^2; fpour; return s; };Dans ce cas, si a<=b la variable j va prendre successivement les valeurs b, b-1,...a (on dit que le pas est de -1) et pour chacune de ces valeurs l’instruction ou le bloc d’instructions qui suit sera exécuté. Par exemple testfor2(1,2) renverra 1/4+1=5/4.
testfor3(a,b):={ local j,s:=0; for (j:=a;j<=b;j:=j+3) s:=s+1/j^2; return s; };ou
testpour3(a,b):={ local j,s:=0; pour j de a jusque b pas 3 faire s:=s+1/j^2; fpour; return s; };Dans ce cas, si a<=b la variable j va prendre successivement les valeurs a, a+3,...a+3k avec k le quotient de b-a par 3 (3k<=b-a<3(k+1)) (on dit que le pas est de 3) et pour chacune de ces valeurs l’instruction ou le bloc d’instructions qui suit sera exécuté. Par exemple testfor3(1,5) renverra 1+1/16=17/16.
testpour4(a,b,p):={ local j,s:=0; pour j de a jusque b pas p faire afficher(j); s:=s+j; fpour; return s; };Selon le signe de p le pour peut se traduire :
testpour41(a,b,p):={ local j,s:=0; for (j:=a;j<=b;j:=j+p){ afficher(j); s:=s+j; }; return s; };
testpour42(a,b,p):={ local j,s:=0; for (j:=a;j>=b;j:=j+p){ afficher(j); s:=s+j; }; return s; };
testpour43(a,b,p):={ local j,s:=0; for (j:=a;j<=b;j:=j+abs(p)){ afficher(j); s:=s+j; }; return s; };
testwhile(a,b):={ while (a==10 or a<b) b:=b-a; return [a,b]; };ou
testtantque(a,b):={ tantque a==10 or a<b faire b:=b-a; ftantque; return [a,b]; };
Un exemple : le PGCD d’entiers
- Version itérative
pgcd(a,b):={ local r; while (b!=0) { r:=irem(a,b); a:=b; b:=r; } return a; };
ou
pgcd(a,b):={ local r; tantque b!=0 faire r:=irem(a,b); a:=b; b:=r; ftantque; return a; };
-Version récursive
pgcdr(a,b):={ if (b==0) return a; return pgcdr(b,irem(a,b)); };
ou
pgcdr(a,b):=if (b==0) return a; else return pgcdr(b,irem(a,b));
f():={ local a; repeat saisir("entrez un reel entre 1 et 10",a); until a>=1 && a<=10; return a; }:;ou
f():={ local a; repeter saisir("entrez un reel entre 1 et 10",a); jusqua a>=1 et a<=10; return a; }:;Voici la fonction qui renvoie un point fixe de f en utilisant repeat. Cette fonction donne la solution à eps près de f(x)=x en utilisant au plus n itérations et x0 comme début de l’itération donné par le théorème du point fixe.
point_fixe(f,n,x0,eps):={ local j,x1,x00; j:=0; repeat x1:=evalf(f(x0)); j:=j+1; x00:=x0; x0:=x1; until (abs(x00-x0)<eps) or (j>=n); return j,x0; }:;ou
point_fixe(f,n,x0,eps):={ local j,x1,x00; j:=0; repeter x1:=evalf(f(x0)); j:=j+1; x00:=x0; x0:=x1; jusqua (abs(x00-x0)<eps) or (j>=n); return j,x0; }:;
point_fixe(f,n,x0,eps):={ local j,x1; j:=0; do x1:=evalf(f(x0)); if (abs(x1-x0)<eps) return x1; x0:=x1; j:=j+1; if (j>=n) break; od; return "non trouve au bout de ", n," iterations"; }:;ou en utilisant faire
point_fixe(f,n,x0,eps):={ local j,x1; j:=0; faire x1:=evalf(f(x0)); if (abs(x1-x0)<eps) return x1; x0:=x1; j:=j+1; if (j>=n) break; ffaire; return "non trouve au bout de ", n," iterations"; }:;On peut aussi écrire cela avec un for
point_fixe(f,n,x0,eps):={ local j,x1; for (j:=0;j<n;j++){ x1:=evalf(f(x0)); if (abs(x1-x0)<eps) return x1; x0:=x1; } return "non trouve au bout de ", n," iteration"; }:;point_fixe(x->cos(x),100,1.0,1e-12)=0.739085133215
pgcd(a,b):={ local r; for (;b!=0;) { r:=irem(a,b); a:=b; b:=r; } return a; } :;ou
pgcd(a,b):={ local r; for (;;) { if (b==0) break; r:=irem(a,b); a:=b; b:=r; } return a; } :;