Scilab et algorithmique

Transcription

Scilab et algorithmique
Chapitre 1
Scilab et algorithmique
I
Présentation du logiciel Scilab
Scilab est un logiciel libre développé par un consortium constitué :
– d’organisations publiques (entre autre l’INRIA, le CNES, le CEA),
– d’entreprises (Peugeot, Renault, EDF, etc.),
– d’écoles et d’universités (entre autres l’école Polytechnique).
On peut le télécharger gratuitement 1 .
Scilab est un logiciel de calculs numériques, il ne sait donc pas gérer des variables qui n’ont
pas de valeurs. Ainsi, il peut calculer cos(x) et cos(-x), si x a une valeur, mais n’a aucune idée de
la signification de la formule cos(x)=cos(-x). De même, il est incapable de faire des calculs du type
√
√
(1 + 2)2 = 3 + 2 2. Il peut vérifier l’égalité 3/2 = 6/4, en calculant les valeurs des deux membres
et en comparant ces valeurs, mais ne simplifiera pas les fractions tout seul.
Par contre, il permet de :
– programmer des fonctions, i.e. des instructions exécutées sur des données et pouvant être
appelées, dans l’espace de travail, voire dans d’autres fonctions.
– travailler avec des données sous forme matricielle de manière efficace. Ainsi, on pourra faire
l’opération A × X, si A et X sont des matrices de tailles compatibles.
– contrôler le flux d’exécution i.e. exécuter certaines instructions plusieurs fois (on parle alors
de boucle), ou choisir les instructions exécutées selon les valeurs d’une variable. Ce contrôle du
flux se fait à l’aide de mots clés, comme if, end, for et while.
– travailler de manière très rapide avec les fonctions mathématiques. La plupart des fonctions
mathématiques sont déjà implémentées, en particulier les algorithmes complexes pour le calcul
des probabilités et le calcul matriciel.
– afficher des résultats sous forme graphique.
Scilab au concours de BCPST Dans la quasi totalité des sujets d’écrit de concours, une question
Scilab est présente, notée entre 2 et 4 points. Il faut donc savoir écrire de petites fonctions Scilab pour
l’écrit. Une erreur de syntaxe sans gravité n’est pas sanctionnée lourdement. Par contre, les erreurs
d’algorithmique sont davantage sanctionnées.
1. Par exemple, sur le site officiel : http://www.scilab.org/.
1
Une épreuve orale d’option est aussi prévue, sous forme d’un projet et d’exercices à l’oral. La
moyenne de l’épreuve tourne autour de 13 et seuls les points au-dessus de 10 sont pris en compte.
Dans les rapports de jury, il est systématiquement rappelé qu’un effort en informatique est payant
et fait gagner des points, à l’écrit comme à l’oral.
Enfin, rappelons que, dans la plupart des écoles que l’on peut intégrer avec une BCPST, un cours
d’informatique est prévu en première année. Il s’agit très souvent d’un cours sur un logiciel de calculs
numériques (Scilab ou Matlab 2 ), ainsi le temps consacré à l’informatique en BCPST n’est pas du
« temps perdu », même si c’est une matière nouvelle par rapport à la classe de Terminale et qui
demande donc un certain investissement au début.
II
Prise en main du logiciel : les trois interfaces de travail
Scilab propose trois environnements de travail : la ligne de commande, les scripts et les fonctions.
La ligne de commande C’est l’interface de travail par défaut : on tape une commande et le calcul
est fait. Le résultat est affiché si la ligne ne finit pas par ;, sinon il est effectué sans affichage. On peut
retrouver les commandes déjà tapées en utilisant ↑.
Application 1 Tapez les commandes dans l’espace de travail, tout ce qui suit le symbole // sont
des commentaires, il est donc inutile de les recopier.
2+2 //exemple de calcul simple
2+2; // le même avec un ;
(1-%i)* 2 // exemple de calcul dans C : %i est le i complexe
3*2 // exemple de multiplication
sqrt(2) // appel d’une fonction mathématique
%pi // constante pi
i*2 // ne pas oublier les %
log 2 // ni les ().
Lorsque le flux d’exécution est suspendu (i.e. lorsqu’on se trouve dans une boucle for ou un if),
alors rien ne se passe jusqu’à ce que l’on entre le mot clé end. Pour indiquer que les exécutions sont
suspendues, les invites de commandes ––> sont rapprochées.
Application 2 Taper les commandes :
for i=1:10
disp(i)
end
Remarquez la manière dont les invites de commandes ––> sont rapprochées.
Ce mode est utile pour des tests rapides, mais les commandes tapées ne peuvent être mémorisées 3 .
D’une manière générale, il est déconseillé de taper des commandes permettant de contrôler le flux
2. Équivalent propriétaire du logiciel Scilab. Le générateur de nombres aléatoires est moins puissant, mais l’interface
est plus agréable.
3. L’historique peut être retrouvé par la commande gethistory.
d’instructions dans la ligne de commande, i.e. dès qu’on utilise if, for ou while, il faut utiliser un
script ou une fonction.
Pour interrompre le flux d’exécution en cas d’urgence, il faut utiliser le raccourci clavier
CTRL+C. L’invite de commande devient -1->, on peut alors annuler le tout en utilisant la commande
abort.
Application 3 Taper les commandes :
i=1;
while (i<10)
disp(i)
end
Pour sortir de l’exécution, utiliser le raccourci clavier CTRL+C, puis la commande abort.
Les scripts Un script est un fichier texte qui contient une suite de commandes. Lorsque le fichier est
exécuté, les commandes sont exécutées une par une, comme si elles étaient tapées dans la ligne de commande. Si une erreur est rencontrée, l’exécution s’arrête. Les scripts permettent donc de sauvegarder
la suite d’instructions effectuées pour pouvoir la refaire.
Pour créer un script, il faut donc utiliser un éditeur de texte 4 , dans lequel on crée un fichier
texte qu’on enregistre, de préférence avec l’extension .sce qui signifie Scilab executable. Puis, pour
exécuter le fichier, il faut utiliser la commande exec(’fichier.sce’), en ayant pris soin de donner à
Scilab le chemin du répertoire contenant le fichier 5 . Bien entendu, il faut sauvegarder le fichier avant
de l’exécuter.
Application 4 Ouvrir l’éditeur, enregistrez dans le fichier presentation.sce la suite d’instructions :
clear; //efface toutes les variables
clc; //efface l’écran
nom=input("Quel est ton nom?","string");
disp("bonjour "+nom);
Exécuter ce script.
La solution à un exercice de Scilab sera donc toujours un script permettant de réaliser l’expérience
demandée.
Pour prendre de bonnes habitudes :
– un script commence par la commande clear; qui permet d’effacer toutes les variables, afin de
bien vérifier que d’éventuelles commandes précédentes n’interviennent pas dans le script.
– Ensuite on charge les différentes fonctions,
– puis la description des constantes,
– enfin l’appel aux fonctions.
Notons, de plus, que rien n’empêche de faire appel à un script dans un script, en utilisant la commande
exec.
4. On peut utiliser celui intégré à Scilab, mais il est peu puissant. Le mieux est donc d’utiliser un programme externe,
par exemple Geany. Voir sur le site web comment configurer Geany pour Scilab.
5. La commande pwd indique le répertoire de travail. On le change avec la commande cd. Il est aussi possible d’utiliser
le menu.
Comme tous les langages de programmation, Scilab permet l’utilisation de commentaires, tout
ce qui suit // étant ignoré. Cette fonctionnalité doit être utilisée pour expliquer ce que fait le code.
Dans les épreuves d’écrit, il est conseillé aussi d’ajouter des commentaires pour expliquer sa démarche.
Un code sans commentaires n’a aucune valeur.
De même, les espaces entre les mots ne sont pas pris en compte lors de l’exécution, ce qui est
particulièrement intéressant pour les tabulations qui permettent de structurer visuellement le code.
Les fonctions Une fonction est une suite d’instructions exécutées sur des entrées permettant le
calcul de sorties. Cette suite d’instructions est enregistrée dans un fichier texte. Les entrées sont
données par l’utilisateur et les instructions n’ont donc un sens pour Scilab qu’à l’appel de la fonction
sur certaines entrées. L’avantage d’une fonction est qu’elle peut être appelée sur n’importe quel type
d’entrée, exactement comme une fonction mathématique. Par exemple, si on considère la fonction
function [out]=f(x,y), on pourra l’appeler sous la forme f(2,i), mais aussi sous la forme 6 f(x,x),
f(2x,y), etc. On pourra aussi utiliser l’instruction f(f(x,y),z).
Il ne faut donc pas donner de valeurs aux variables d’entrées dans la fonction. Une fonction du
type f : x 7→ x2 + 3x + 2, qui serait implémentée sous la forme :
function out=f(x)
x=2;
out=x^2+3*x+2;
endfunction
ne fera que renvoyer la valeur 12, ce qui n’est absolument pas la fonction demandée.
De même, une fonction doit systématiquement donner une valeur aux sorties, sinon elle ne calcule
rien. La fonction f doit donc contenir une instruction du type out=, où out est le nom de la variable
de sortie 7 . Ces deux erreurs (donner une valeur aux entrées dans la fonction et ne pas donner de
valeur aux sorties) sont considérées comme des erreurs d’algorithmique.
La syntaxe d’une fonction est très particulière. Il faut indiquer à Scilab que les variables en entrée
n’ont pas de valeurs, et que les instructions n’auront de sens que lors de l’appel de la fonction.
Une fonction doit donc toujours commencer par une ligne
function [y1,y_2, ... , yn]= nom_fonction(x1,x2 ... , xm)
où les xi sont les entrées, tandis que les yi sont les sorties, et finir par la commandeendfunction.
La fonction est ensuite ajoutée à Scilab via la commande exec(’fichier.sci’), l’extension .sci
(« Scilab Input ») étant conseillée pour les fichiers de fonctions. Il est aussi conseillé d’utiliser un
fichier par fonction, le fichier portant le nom de la fonction.
Si Scilab détecte une erreur de syntaxe (si, par exemple, il manque un end), il émet une erreur en
indiquant la ligne correspondante. Si la fonction est correctement chargée, une nouvelle variable est
alors créée dans Scilab, portant le nom de la fonction. Une fonction peut ainsi être utilisée comme
entrée d’une autre fonction.
La fonction peut alors être exécutée, en tapant la commande correspondante, les entrées étant
indiquées dans une parenthèse.
Par exemple, on doit entrer dans l’éditeur les lignes :
6. Si x est une variable qui a déjà une valeur évidemment.
7. Ceci étant valable bien sûr pour toutes les sorties si il y en a plusieurs.
function out=f(x,y)
out=cos(x)*y;
endfunction
Ces lignes doivent être enregistrées dans un fichier f.sci. Ensuite, on doit charger la fonction,
i.e. exécuter la commande exec(’f.sci’). On peut ensuite l’appeler avec, par exemple :
f(%pi/4,%i);//renvoie 0.7071068i
x=2;y=4;
z=f(x+y,y);//stocke - 1.117662 (soit 4sin(6)) dans z
f(f(1,1),0.3) // exemple de composition.
Si il y a plusieurs sorties, seule la dernière est affichée, le reste peut être récupéré en stockant les
valeurs de sorties.
Par exemple :
function [u,v]=f(x,y)
u=x+y;
v=x-y;
endfunction
La commande f(3,4) ne renverra que la valeur 7. Pour récupérer la valeur -1, il faut taper :
[x,y]=f(3,4); la variable x contiendra alors 7, et y contiendra -1.
Notons enfin que les instructions de la fonction ne sont effectuées que lorsque la fonction est
appelée, ce qui peut poser des problèmes si la fonction est appelée sur des entrées, en dehors de son
domaine de définition.
Par exemple, une fonction f : (x, y) 7→ . . . définie si (x, y) ∈ R2 , et contenant l’instruction if
x < y, ne posera aucun problème lors du chargement de la fonction. Par contre, un appel de la
fonction du type f (i, 4) provoquera un message d’erreur. C’est pourquoi, il est conseillé d’écrire des
commentaires, au début d’une fonction, un petit descriptif des entrées et des sorties. De même que
l’on doit préciser le domaine de définition d’une fonction en mathématiques.
Enfin, pour modifier une fonction, il faut modifier le fichier, puis le sauvegarder et le recharger (de
nouveau avec la commande exec). Un avertissement est alors affiché pour signaler que la fonction est
redéfinie : Warning :redefining function: nomfonction.
Application 5 Ouvrir l’éditeur et sauvegardez dans le fichier demandeAge.sci les lignes :
function age=demandeAge(prenom)
//entrée: prenom (chaîne de caractère)
//sortie: age (réel)= âge donné
//Cette fonction demande l’âge de la personne dont le prénom est en entrée
disp("Bonjour "+ prenom);
age=input(prenom+ ", quel est ton âge?");
endfunction
Pour appeler cette fonction :
– enregistrez votre fichier,
– chargez la fonction avec la commande exec(’’demandeAge.sci’’);
– appelez-la avec une commande du type demandeAge(’’toto’’);
Que se passe-t-il si on appelle la fonction avec demandeAge(5); ?
Modifier la fonction pour qu’elle affiche merci à la fin.
III
Algorithmique : Écrire un programme
Définition 1. Un algorithme est une suite finie d’instructions déterministes permettant d’effectuer un calcul, d’obtenir la valeur d’une fonction ou, d’une manière générale, de résoudre un problème.
On s’intéressera en mathématiques à des algorithmes du type :
√
– a étant donné, calculer une approximation de a, en donnant une marge d’erreur sur cette
approximation.
– A et b étant donnés, résoudre le système Ax = b.
– Renvoyer une approximation de π par la méthode de Monte-Carlo en utilisant 1000 lancers.
π
– Calculer une valeur numérique de sin( 21
).
– Trouver la trajectoire d’un pendule soumis à la gravité.
Mais l’informatique peut aussi être utilisée pour :
– modéliser sous forme graphique la propagation d’un feu dans une forêt ou les déplacements de
fourmis à la recherche de nourriture,
– étant donné une position sur un jeux d’échecs, donner la liste des coups possibles.
Plusieurs remarques s’imposent :
– par instruction, on entend un « ordre donné à l’ordinateur », c’est-à-dire faire un calcul, appeler
une fonction, affecter une variable, effectuer un test, etc, mais en aucun cas, on ne peut prendre le
point qui réalise le maximum de la fonction f sur l’intervalle [0, 1], si on ne dispose pas de moyens
effectifs de calculer ce maximum. C’est la différence entre l’informatique et les mathématiques :
en mathématiques on peut montrer l’existence de certains objets, en informatique, on a besoin
de pouvoir les calculer.
– utiliser des instructions déterministes n’empêche par l’utilisation d’aléatoires. En fait implicitement un générateur de nombres aléatoires est ajouté aux entrées. Par contre, étant donné des
entrées identiques (dont le générateur aléatoire), les sorties seront identiques, encore une fois
comme pour une fonction en mathématiques.
– le problème de la finitude est complexe : il faut pouvoir prouver qu’un algorithme s’arrête et
ne boucle pas indéfiniment, en particulier dans le cas d’algorithmes récursifs, qui s’appellent
eux-mêmes.
– s’ajoute à ces notions une définition de l’efficacité. Un algorithme doit faire le moins de calculs
possibles pour calculer la sortie, de manière à diminuer le temps de calcul. De plus, un algorithme
doit, si possible, utiliser le minimum d’espace mémoire.
IV
Utilisation de variables
La première notion informatique liée à celle d’algorithme est la notion de variable : une variable
est un bloc de mémoire qui est nommé.
Ainsi, l’instruction a=2; alloue un bloc de mémoire dans la RAM et y insère la valeur 2. On parle
d’affectation de la variable a. Le caractère a fait alors référence à ce bloc de mémoire. Lorsqu’on tape
l’instruction b=a+2, le bloc de mémoire est lu, l’opération est effectuée et le résultat est stocké dans
la variable b. Ainsi, le = en informatique n’a pas le même sens que le = mathématique, en particulier
l’instruction b=a n’est pas identique à l’instruction a=b :
– b=a lit le contenu de la variable a, et stocke ce contenu dans la variable b, a n’est donc pas
modifiée,
– a=b lit le contenu de la variable b, et stocke ce contenu dans la variable a, b n’est donc pas
modifiée. C’est donc exactement le contraire.
Cette remarque permet d’utiliser des instructions comme a=a+2, qui ajoute 2 au contenu de la
variable a. Ainsi, pour itérer une fonction à partir d’un point a, i.e. pour calculer les termes d’une suite
(un ) définie par u0 = a et un+1 = f (un ), si on n’a besoin que du dernier terme de la suite, on pourra
utiliser l’instruction x=a, pour initialiser une variable x à la valeur de a, puis répéter l’instruction
x=f(x).
Si on utilise une variable non affectée, on obtient alors un message d’erreur explicite undefined
variable : x. Utiliser une variable sans lui avoir donner de valeur est considéré comme une faute
d’algorithmique. Bien entendu, dans une fonction, les variables en entrées sont supposées être affectées,
ou plus exactement sont affectées lors de l’appel de la fonction.
Application 1
Tapez la suite de commandes, et observez le résultat :
a=1; //affectation de variables le ; évite l’affichage
a
b=a+3;
b
b=a+3 // influence du ;
2*b
(2b-1) /2 //ne pas oublier les *
b*2-1/2 // corrigez en utilisant la flèche
(b*2-1)/2 // attention aux parenthèses
B // B est différent de b
Application 2
Effacez l’espace de travail avec la commande clear; puis tapez la commande :
a=a+3;
Que se passe-t-il ?
Application 3 Si l’on exécute la suite de commande :
a=2;
a=a*a;
a=a*a;
a=a*a;
Que contient la variable a ?
Application 4 Si l’on effectue la suite de commande :
a=5;
b=3;
c=a;
a=b;
b=c;
Quelles valeurs contiennent les variables a et b ? Cette technique permet de transférer la valeur d’une
variable dans une autre.
Application 5 Calculez rapidement le 5-ième terme de la suite définie par : u0 = 2, et un+1 =
un sin(un ). Proposez une méthode avec une fonction et une sans.
Les types de données que peut contenir une variable en Scilab sont principalement :
– un réel,
– un complexe, en utilisant %i,
– une chaîne de caractères,
– une matrice ou un vecteur (considéré comme une matrice avec une unique ligne/colonne),
– une variable booléenne %t (vraie=true) ou %f (fausse=false),
– une fonction.
La commande who_user permet d’afficher le nom des variables affectées 8 , et la commande clear
permet d’effacer l’espace de travail, i.e. toutes les variables affectées. Pour connaître la valeur
d’une variable, il suffit de taper son nom sans ajouter le ;, la valeur est alors affichée. Une commande
graphique permet d’éditer les variables, c’est la commande browsevar();.
Portée des variables La manière dont les variables peuvent être utilisées par une fonction dépend
de la portée d’une variable, i.e. du domaine dans lequel cette variable a une valeur :
– une variable affectée dans l’espace de travail est globale, c’est-à-dire qu’elle est connue dans
toutes les fonctions. Ainsi, si dans l’espace de travail on a défini une variable f , n’importe quelle
fonction peut utiliser cette variable. Ceci est particulièrement utilisé si f est une fonction. On
peut considérer que l’ensemble de l’espace de travail est implicitement ajouté en entrée d’une
fonction.
– de telles variables peuvent être modifiées dans une fonction, mais c’est alors leur valeur locale
qui est modifiée par la fonction, mais pas dans l’espace de travail. Par exemple, si dans l’espace
de travail on définit n=3, une fonction pourra utiliser le contenu de la variable n et faire des
opérations du type n=n+1, mais une fois sortie de la fonction, la valeur de n sera toujours 3.
Cela est vrai aussi, et particulièrement utilisé pour les entrées d’une fonction : si une fonction
y=f(x) modifie son entrée en utilisant des instructions du type x=x-1, l’appel de la fonction
avec une instruction du type f(x) ne modifie pas la valeur de x dans l’espace de travail.
– pour éviter toute erreur, il est ainsi conseillé d’utiliser uniquement des variables locales, i.e.
une fonction doit pouvoir fonctionner uniquement avec ses entrées. C’est de toute manière sous
cette forme que sont demandées les fonctions lors des épreuves d’écrit.
– une variable utilisée par une fonction est locale. Ainsi, si une fonction définit et utilise une
variable n, n n’aura pas de valeur en dehors de la fonction, ce qui permet de ne pas « ajouter »
de nouvelle variable. En particulier, appeler une fonction définie par y=f(x) avec l’instruction
f (2) ne définit pas de variable y. On peut ainsi appeler la fonction sur une variable nommée z
et stocker le résultat dans une variable nommée x, etc. Peu importe le nom de la variable dans
la fonction, cela n’intervient pas sur les variables de l’espace de travail.
8. D’autres variables « système » sont aussi affichées, il suffit de ne pas en tenir compte.
Ainsi, on peut comparer une fonction Scilab à une boîte noire, calculant une sortie donnée à partir
d’entrées et des variables contenues dans l’espace de travail, mais ne modifiant pas l’espace de travail.
Application 6 Écrire une fonction du type :
fonction y=f(x)
x=x+1;
y=x^2;
endfunction
La lancer avec la suite de commandes :
exec("f.sci");
a=3;
f(a)
Quelle est la valeur de la variable a, celle de la variable x et celle de la variable y ?
Si on tape ensuite dans la ligne de commande :
x=5;
f(x^2)
Quelle est la valeur affichée ? Quelle est la valeur de la variable x ?
Erreurs de syntaxe classiques avec les variables :
– Scilab fait la différence entre majuscule et minuscule.
– il faut utiliser le symbole * pour une multiplication, 2b renvoie une erreur. Pour éviter cette
confusion, on ne peut pas utiliser une variable commençant par un chiffre.
– les lettres grecques ne sont pas acceptées, ainsi que les lettres accentuées dans les noms de
variables. On utilisera donc des noms de variables du type phi.
– les instructions d’affection des variables doivent être de la forme
variable=expression. Une expression du type 3=a est une erreur d’algorithmique, ainsi que
a+b=c+d, qui n’a aucun sens en informatique.
– dans une instruction de la forme variable=expression, c’est d’abord expression qui est
évaluée et ensuite le résultat est stocké dans variable. Ainsi, l’instruction b=a+b; calcule a+b
et stocke le résultat dans b.
– pas d’accents ni d’espace dans les noms de variables.
V
Contrôle du flux d’exécution
Le contrôle du flux d’exécution permet d’exécuter certaines instructions plusieurs fois, ou selon la
valeur de certaines variables.
V.1
Variables booléennes et instructions conditionnelles if
Variable booléenne Une variable booléenne est l’équivalent informatique d’une proposition mathématique. C’est donc une variable qui ne peut prendre que deux valeurs : true (T) ou false
(F).
Pour la définir, on utilise un opérateur de comparaison , c’est-à-dire >,<,==,>=,<=,˜=. Il
existe deux possibilités pour 6= : ~= et <>.
Par exemple, si on a défini deux variables x et y, l’instruction x==y renvoie la valeur true si les
variables ont la même valeur, false sinon. On utilise == pour bien signifier qu’il ne s’agit pas d’une
affectation. L’instruction x=y (qui met la valeur de y dans la variable x) est très différente de x==y
qui compare les deux valeurs 9 . Attention à ne pas confondre ces deux instructions : cela peut être
considéré comme une erreur d’algorithmique. On retiendra donc qu’il faut toujours mettre == dans
un test.
Les variables booléennes peuvent être combinées à l’aide des opérateurs ~, & et | , équivalents en
mathématiques à non, et et ou respectivement.
Remarque: Mathématiquement, la proposition « p et q » est fausse dès que p est fausse. Du
coup, lorsque Scilab rencontre une variable booléenne du type « p et q », il commence à regarder la
valeur de p. Si celle-ci est fausse, alors, il n’a pas besoin de regarder la valeur de q.
D’une part, cela évite des tests, et donc du temps de calcul inutile, mais l’application la plus
importante est surtout que si p est fausse, la variable q peut-être indéfinie.
L’exemple typique est celui d’un tableau : si on doit lire l’élement i dans un tableau tab de taille
n, il faut s’assurer que i ∈ [[1, n]].
On rencontrera, par exemple le test :
if (i<=n) & (i>=1) & (tab(i)==0)
qui teste d’abords si i ∈ [[1, n]], avant de comparer la valeur de la case i de tab à 0. Si la valeur de i
n’est pas dans l’intervalle, alors tab(i) n’est pas lu. Au contraire, si on avait écrit :
if (tab(i)==0) & (i<=n) & (i>=1)
alors, si la valeur de i n’est pas dans l’intervalle, Scilab renverra une erreur puisqu’on essaie de lire
un élément qui n’existe pas.
On peut donc dire qu’en informatique « p et q » n’est pas rigoureusement identique à « q et p ».
Instructions conditionnelles : if Les variables booléennes sont surtout utilisées pour des instructions conditionnelles, c’est-à-dire que l’on peut donner des instructions différentes à l’ordinateur
selon la valeur d’une variable booléenne. On contrôle le flux d’exécution selon la valeur des variables
booléennes.
De même qu’en mathématiques on peut définir la fonction
x 7→
on peut définir la fonction Scilab :

 sin(x)
x
0
si x 6= 0
sinon
,
function y=f(x)
if (x==0)
y=0;
else
9. Notons d’ailleurs que x==y est identique à y==x, alors qu’on a vu que x=y est le contraire de y=x.
y=sin(x)/x;
end
endfunction
La syntaxe générale d’une instruction if est donc :
if (test) then
//bloc d’instructions si test vrai
else
//bloc d’instructions si test faux
end
Le then est optionnel, il peut être remplacé par un retour à la ligne. La partie else est aussi optionnelle : il peut très bien n’y avoir aucune instruction si la condition est fausse.
Application 1 Écrire une fonction out=potentielHydrogene(pH) qui prend en entrée un nombre
pH, et qui renvoie 1 si le ph est basique, 0 si il est neutre, et -1 si il est acide. Modifiez la fonction
pour qu’elle sorte une chaîne de caractères : basique, neutre ou acide (selon les cas).
On peut enchaîner les instructions conditionnelles en utilisant elseif, qui permet d’éviter de
devoir mettre plusieurs end. La syntaxe de base est :
if (test) then
//bloc d’instructions si test1 vrai
elseif(test2) then
//bloc d’instructions si test1 faux et test2 vrai
else
//bloc d’instructions si test1 faux et test2 faux
end
Par exemple, l’implémentation de la fonction :
signe :
peut s’écrire :
function y=signe(x)
if (x>0) then
y=1;
elseif(x<0) then
y=-1
else
y=0
end
endfunction
x 7→



1


si x > 0
−1 si x < 0



0
sinon
Comme on le voit, il est important de tabuler correctement le programme pour voir clairement
quelles sont les instructions répétées.
On peut aussi imbriquer les structures conditionnelles avec la syntaxe :
if (test1)
//début des instructions si test1 vrai
...
if(test2)
//instructions si test1 vrai et test2 vrai
end//fin du if(test2)
//suite et fin des instructions si test1 vrai
else
//début des instructions si test1 faux
...
if(test3)
//instructions si test1 faux et test3 vrai
else
//instructions si test1 faux et test3 vrai
end//fin du if(test3)
//suite et fin des instructions si test1 faux
end
Pour éviter toute confusion, il vaut mieux écrire, en commentaire, à quel if correspond chaque end.
V.2
Instructions répétées : boucles
Une boucle et un bloc d’instructions qui est répété plusieurs fois. Il existe deux manières de faire
des boucles : les boucles for et les boucles while.
Boucle for Si on connaît d’avance combien de fois il faut répéter le bloc d’instructions, on utilise
alors le mot clé for, qui permet d’indexer le nombre de répétitions sur une variable.
La syntaxe est :
for var=début:pas:fin
//bloc d’instructions
...
end
Cela permet d’initialiser une variable (ici var) à la valeur début. Ensuite, le bloc d’instructions entre
le for et le end est exécuté. Dans ce bloc, on peut utiliser (ou pas) la valeur de la variable var. Ensuite,
la variable var est incrémentée de la valeur pas. Si la variable var est inférieure ou égale à la valeur
de fin, le bloc d’instructions est de nouveau exécuté et la variable de nouveau incrémentée. Lorsque
la variable var dépasse la valeur de fin, l’instruction continue après le end (on dit que l’instruction
sort de la boucle). Le pas peut-être omis et vaut alors 1 par défaut.
Considérons, par exemple, une fonction qui calcule la somme des n premiers entiers. Elle peut être
implémentée avec une boucle for :
function y=somme(n)
// entrée: n entier,
// sortie: y somme des n premiers entiers
y=0;
for i=1:n
y=y+i;
end
endfunction
Application 2
À l’aide d’une boucle for, calculer 7!
Application 3 À l’aide d’une boucle for, calculer la somme des carrés des vingt premiers nombres
entiers.
Quelques remarques : Il faut initialiser la variable y à 0 pour pouvoir utiliser l’instruction
y=y+i qui permet d’ajouter i à y. Pour un calcul de somme, il est judicieux d’initialiser y à 0. Pour
un calcul de produit, on préfèrera évidemment, l’initialiser à 1. Si y est un vecteur et qu’on ajoute à
chaque itération une composante, alors on peut l’initialiser à la matrice vide : y=[]. Enfin, si y est
une chaîne de caractères, on pourra l’initialiser à la chaîne vide via y="";.
Le nombre de répétitions dans une boucle for peut être déterminé à l’avance : c’est le nombre de
valeurs possibles pour la variable var.
Rien n’empêche de faire des boucles du type : for k=10:-1:1, i.e. avec un pas négatif. Le programme précédent peut être écrit sous la forme :
function y=somme(n)
// entrée: n entier,
// sortie: y somme des n premiers entiers
y=0;
for i=n:-1:1
y=y+i;
end
endfunction
Une boucle telle que fin>debut est ignorée : l’exécution ne rentre jamais dans la boucle. Enfin, il
n’est pas nécessaire que la variable var passe exactement par fin : par exemple, i=1:2:10 permettra
d’effectuer la boucle 5 fois (pour i=1,3,5,7 et 9).
Boucle while Si la boucle ne se finit que lorsqu’une condition est réalisée, on utilise alors une
boucle while qui permet de répéter un bloc d’instructions jusqu’à ce qu’une condition appelée test
d’arrêt soit atteinte.
La syntaxe est :
while (test)
//bloc d’instructions répété jusqu’à ce que test soit faux
...
end
L’instruction teste la valeur du booléen test, qu’on appelle test d’arrêt. Si cette valeur est
fausse, l’exécution continue jusqu’au end. Ensuite, le test d’arrêt est de nouveau évalué et le bloc
d’instructions est répété. On ne sort de la boucle que si le test est faux.
On ne peut donc pas déterminer le nombre de passages dans la boucle à l’avance. Le problème de
la finitude se pose donc clairement : il faut prouver que l’on sort de la boucle.
Notons que si le test d’arrêt est faux dès le départ, on ne rentre jamais dans la boucle.
On peut aussi écrire la somme des n premiers entiers avec une boucle while :
function y=somme(n)
// entrée: n entier,
// sortie: y somme des n premiers entiers
y=0;
while(n>0)
y=y+n;
n=n-1;
end
endfunction
Quelques remarques : Ici, on utilise directement la variable d’entrée n comme la variable de
test qui va donc être modifiée par la fonction. Mais c’est la copie locale de la variable qui est modifiée.
Ainsi, si on tape les commandes x=5; somme(x); la variable x vaudra toujours 5.
On pourrait aussi écrire
function y=somme(n)
// entrée: n entier,
// sortie: y somme des n premiers entiers
y=0;
i=1;
while(i<=n)
y=y+i;
i=i+1;
end
endfunction
Cela impose d’ajouter une variable i.
Enfin, il faut faire attention à l’ordre des opérations et au test. Par exemple, dans cette dernière
fonction, si on remplace while(i<=n) par while(i<n), on fait une erreur d’algorithmique, puisqu’il
manquera une exécution de la boucle : on n’ajoutera pas la valeur n. Autre erreur, si on renverse les
deux lignes du bloc while, en écrivant :
function y=somme(n)
// entrée: n entier,
// sortie: y somme des n premiers entiers
y=0;
i=1;
while(i<=n)
i=i+1;
y=y+i;
end
endfunction
On fait de même une erreur d’algorithmique, puisqu’on ajoutera les valeurs 2, 3 . . . n + 1, au lieu de
1, 2, . . . n.
Pour éviter les erreurs, le plus simple est de tester au brouillon l’algorithme sur de faibles valeurs,
en écrivant toutes les instructions envoyées à l’exécution. Dans l’exemple ci-dessus, en testant pour
n=3, on obtient les instructions :
y=0;
i=1;
//rentrée dans la boucle (i=1)
i=i+1;// i vaut 2
y=y+2;//y vaut 2
//deuxième passage par while, (i=2)
i=i+1;//i vaut 3
y=y+3;//y vaut 5
//troisième passage par whle, (i=3)
i=i+1;//i vaut 4
y=y+4; y vaut 9.
//fin du while car (4>3)
Application 4 Algorithme de Syracuse On choisit un entier quelconque. S’il est pair, on le
divise par 2, sinon on le multiplie par 3 et on ajoute 1. Puis on répète ce processus jusqu’à arriver à
1.
Cet algorithme se termine toujours en un nombre fini d’itérations.
Écrire une fonction qui prend en entrée un entier et :
– affiche à l’écran la suite des itérés,
– renvoie le nombre d’itérations qui ont été nécessaires pour revenir à 1.
Quand utiliser while ? Les boucles while sont donc plus facilement sources d’erreurs, mais indispensables dès qu’on ne sait pas à l’avance combien d’itérations vont être nécessaires.
C’est le cas, par exemple, si on cherche le point fixe d’une fonction. En itérant une suite un+1 =
f (un ), on exécute alors la suite d’instructions :
x=a;
while(f(x)~=x)
x=f(x)
end
La boucle continue jusqu’à ce qu’un point fixe soit atteint. Bien entendu, l’algorithme n’est valide que
parce qu’il se finit, i.e. parce qu’on a prouvé qu’on converge.
Autre exemple : supposons qu’on souhaite poser la question Voulez vous continuer ? jusqu’à obtenir
la réponse o ou n. On utilise alors une boucle while, selon cette syntaxe :
rep="";//on pourrait mettre n’importe qu’elle valeur différente de o ou n
while ( (rep<>"o")&(rep<>"n"))
rep=input("Voulez-vous continuer?","string");
end
Ce bloc de commande peut lui-même être inclus dans une boucle while du type : while (rep=="o"),
en ayant pris soin d’initialiser la variable rep à "o" de manière à rentrer au moins une fois dans la
boucle.
VI
Algorithmique élémentaire
Le problème de l’échange de deux variables Soient deux variables a et b. Pour échanger les
valeurs contenues dans ces variables, il faut passer par une variable auxiliaire généralement nommée
tmp ou aux pour bien montrer son caractère temporaire. Il faut ainsi utiliser les instructions tmp=a;
a=b; b=a;
Cette remarque s’étend aux calculs d’affectations les unes à la suite des autres. Par exemple, si
on veut calculer les termes des suites (an ) (bn ) définies par :
∀n ∈ N,
(
an+1 =
bn+1 =
√
an bn
an +bn
2
et qu’on ne veut garder que la dernière valeur. On ne peut pas utiliser les expressions :
a=sqrt(a*b);b=(a+b)/2; car, dans ce cas, la deuxième instruction utilise, non pas la valeur de a
originale, mais celle modifiée par la première instruction. Il faut donc encore passer par une variable
temporaire, par exemple : tmp=sqrt(a*b);b=(a+b)/2;a=tmp;.
Attention à ce type d’erreur d’algorithmique, qui ne pose aucun problème de syntaxe, mais ne
donnera jamais le bon résultat.
Conserver ou pas des variables Supposons qu’on considère la suite de Fibonnaci un définie par
u1 = 1 et u2 = 1 un+2 = un+1 + un .
Pour écrire une fonction qui renvoie la valeur de un en fonction de n, on doit a priori sauvegarder toutes les valeurs des (uk )k<n dans la fonction, en utilisant un vecteur de taille n, contenant
[u1 , u2 , u3 . . . , un ], et ensuite ne renvoyer que la dernière composante du vecteur 10 .
Cela s’écrit :
function out=fibbo(n)
// n entier naturel
// out = valeur du n-ième terme de la suite de fibbonacci
u=[1,1]; //initialisation du vecteur u, par les deux premiers termes
for i=3:n
//on ajoute une composante au vecteur u somme des deux composantes précédentes:
u(i)=u(i-1)+u(i-2);
end
10. Voir le chapitre suivant pour la manipulation de vecteurs/matrices en Scilab. Ici, on se sert uniquement du fait
que u(i) est la i-ème composante du vecteur i.
out=u(n);
//rem: si n<3, on ne rentre pas dans la boucle, le résultat est donc valable
endfunction
Le défaut de cette méthode est qu’il y a une perte de mémoire. Pour calculer u1000 , on n’a pas
besoin des 999 termes précédents, mais uniquement de 2 : u999 et u998 .
On peut donc raisonner différemment. On utilise deux variables : un pour la valeur de un et unm1 11
pour la valeur de un−1 . À chaque itération, i.e. pour passer de n à n + 1, on doit mettre à jour la
variable un comme la somme de la valeur de un et de un−1 . Ainsi, un contient bien la valeur de un+1 .
On écrit donc l’instruction : un=un+unm1;. Il faut aussi modifier la valeur de la variable unm1 pour
qu’elle contienne, non plus un−1 , mais la valeur de un , qui était contenue dans la variable un avant
modification et qu’on aura donc pris la peine de sauvegarder dans une variable temporaire.
Le programme devient alors :
function out=fibbo(n)
// n entier naturel
// out = valeur du n-ième terme de la suite de fibbonacci
un=1;//les deux valeurs sont initialisées à 1
unm1=1;
for i=3:n
//on sauvegarde la valeur de un:
tmp=un;
//la valeur courante est mise à jour: c’est la somme des deux valeurs précédentes
un=un+unm1;
//la valeur de unm1 est mise à jour: c’est la valeur de un sauvegardée
unm1=tmp;
end
out=un;
//rem: si n<3, on ne rentre pas dans la boucle, le résultat est donc valable
endfunction
Ce dernier algorithme utilise beaucoup moins de variables.
Cette idée se comprend aussi facilement dans le cas du calcul du terme un dans une suite définie
par un+1 = f (un ), en fonction du premier terme u0, de la fonction f et de n.
On pourrait écrire ce programme sous la forme :
function y=suite(n,f,u0)
// n entier naturel
// f fonction telle que la suite récursive est bien définie en partant de u0
// u0 premier terme
// y = valeur du n-ième terme de la suite définie par u0 et u(n+1)=f(u(n))
u=[u0];//initialisation de u à un vecteur ne contenant que le terme u0
for i=1:n
u(i)=[u,f(u(i-1)];//ajout d’une composante au vecteur u
11. Abréviation de « u n moins 1 ».
end
out=u(n+1);
endfunction
Cette fonction construirait donc un long vecteur de taille n+1, contenant [u0 , u2 , . . . , un+1 ]. À chaque
itération, une composante est ajoutée 12 au vecteur u, cette nouvelle composante étant l’image de la
précédente par la fonction f.
On pourrait aussi écrire cette fonction sous la forme plus condensée :
function y=suite(n,f,u0)
y=u0;//initialisation de y
for i=1:n
y=f(y);//on remplace y par son image par f
end
endfunction
Quelques remarques : La fonction f est ici une entrée de la fonction suite. on utilise ici le fait
qu’on peut mettre une fonction en entrée d’une autre fonction.
Si on demande, dans une copie, d’écrire une fonction qui ne dépend que de n et de u0, et qui permet
de calculer le n-ième terme d’une suite définie par u0 et par exemple : un+1 = sin(un ) + cos(un ), on
a tout intérêt à définir la fonction f dans la fonction suite 13 . Cela donnera :
function y=suite(n,u0)
//définition de la fonction f:
deff("y=f(x)","y=cos(x)+sin(x)");
y=u0;//initialisation
for i=1:n
y=f(y);//on remplace y par son image par f
end
endfunction
Décalage d’indices En Scilab, les indices commencent à 0 et non à 1. On a déjà rencontré cette
difficulté pour le calcul de la suite u(n), lorsqu’on a écrit :
u=[u0];//initialisation
for i=1:n
u(i)=[u,f(u(i-1)];//ajout d’une composante au vecteur u
end
out=u(n+1);
Du point de vue mathématique, on calcule un vecteur qui contient [u0 , . . . , un ], mais avec Scilab, les
éléments du vecteur sont [u(1),u(2),u(3)... u(n+1)]. Ce vecteur est donc de taille n+1, et l’indice
i en Scilab correspond donc à l’indice mathématique i − 1. Il faut donc veiller à ne pas faire d’erreur
lors du passage entre les deux indices.
12. Ici aussi, voir la partie sur les matrices/vecteurs. On utilise simplement le fait que si u est un vecteur de taille n,
[u,a] est un vecteur de taille n+1, obtenu en concaténant a au vecteur u.
13. Attention, la fonction suite ne sera alors valable que pour cette fonction f particulière. La fonction f n’est plus
une entrée de la fonction suite.
VII
À savoir
Utiliser l’aide
MotCle
L’aide en ligne est disponible via les commandes help NomFonction ou apropos
Érreurs d’arrondis Scilab ne fait que des calculs approchés et fait donc des erreurs numériques. À chaque calcul, une erreur est faite. Un des buts des mathématiques est donc de contrôler
la propagation de ces erreurs.
Par exemple, supposons qu’on exécute les lignes de code :
clear;
x=0;
for i=1:30
x=x+0.1;
end
En théorie, la valeur de x est alors 3, ce qui est d’ailleurs la valeur affichée par Scilab. Pourtant,
le test x==3 renverra la valeur F. Les erreurs d’arrondis faites durant les 30 additions font que la
valeur de x est différente de 3, ce qui peut se vérifier en utilisant la commande : format(25), qui
permet de modifier la précision de l’affichage. La valeur de x avec cette précision est alors : x=
3.0000000000000013322676 .
Autre exemple : si on demande à Scilab d’inverser une matrice, puis de multiplier la matrice par
l’inverse, on n’obtient pas exactement l’identité.
-->A=rand(4,4);A*A^{-1}
ans =
1.
1.958D-16
2.147D-17
1.786D-16
1.471D-16
1.
1.269D-17
4.605D-17
1.718D-16
- 8.496D-17
1.
- 1.455D-16
- 3.771D-16
- 2.040D-16
6.635D-17
1.
Les termes hors diagonaux sont quasi nuls.
Dernier exemple, la suite de commandes
n=2;i=1
while (n<n^2)
i=i+1;
n=n^2;
end
disp(i)
se termine et affiche une valeur de i. En effet, Scilab ne peut gérer des entiers trop grands.
Quand utiliser un script et quand utiliser une fonction ? Pour comprendre la différence entre
√
un script et une fonction, considérons, par exemple, le cas du calcul de a par la méthode de Newton,
i.e. en itérant la fonction f (x) = 21 x + xa . La suite d’instructions :
clear;
n=10;//nombre d’itérations
y=2;
deff("y=f(x)","y=0.5*(x+ (a/x))");
for i=1:n
y=f(y);
end
y //y est la valeur calculée
√
Cette suite d’instructions peut être rentrée dans un script, qui permet alors de calculer 2, en
itérant 10 fois la fonction f . Cette méthode peut servir de test, mais elle n’est pas très souple :
– si on veut augmenter le nombre d’itérations, on est obligé de changer la valeur de n, puis de
sauvegarder et de relancer le script avec exec.
– idem, si on veut changer la valeur 2.
– il faut savoir que y est la valeur calculée. Dans le cas où y est déjà une variable allouée, il faut
remplacer (partout) y par z.
Pour toutes ces raisons, il est préférable de rentrer ces valeurs dans une fonction. Cette fonction
prend en entrée a et n et retourne la valeur trouvée de y 14 . Cette fonction s’écrit :
function y=newton(a,n)
y=a;
deff("y=f(x)","y=0.5*(x+ (a/x))");
for i=1:n
y=f(y);
end
endfunction
Ensuite, cette fonction peut être appelée par une instruction du type f(2,10), f(3,20), etc. Le
résultat peut être stocké dans une variable z, en posant z=f(3,10). De plus, si y a une valeur dans
l’espace de travail, cette valeur n’intervient pas.
Un autre exemple parlant est le cas des entrées sorties au clavier. Un script qui demanderait un
entier en utilisant la commande input, calculerait et afficherait son carré, a un intérêt pédagogique,
mais aucun intérêt pour représenter la fonction x 7→ x2 sur [0, 1], puisqu’il faudrait rentrer des
centaines de valeurs à la main entre 0 et 1 et noter leur carré.
Enfin, en informatique, on s’intéresse aux propriétés d’un algorithme comme celui de Newton.
Par exemple, on se demande si, lorsqu’on augmente les itérations, on obtient vraiment une meilleure
approximation. Ou, on veut savoir si il y a des valeurs de a pour lesquelles la convergence est plus ou
14. Généralement, les entrées et les sorties sont données par l’énoncé. Il faut respecter, dans ce cas, ce qui est demandé
dans l’énoncé.
moins rapide. Ainsi, il est conseillé d’écrire, en parallèle de la fonction, une « démo » de cette fonction,
qui va être un script appelant la fonction sur diverses valeurs pour la tester.
Par exemple, on écrira un script sous la forme :
clear;
exec("newton.sci");
//test avec a=2 et n=10
y=newton(2,10);
disp(y,"valeur trouvée");
disp(abs(y-sqrt(2)),"erreur commise");
//test avec a=3 et n=10
y=newton(3,10);
disp(y,"valeur trouvée");
disp(abs(y-sqrt(3)),"erreur commise");
Dans un exercice de Scilab, il est ainsi conseillé de fournir un couple script/fonction. La fonction
contient l’algorithme demandé, et le script quelques tests permettant de prouver sa validité et de
montrer son fonctionnement.
Les fonctions Scilab à connaître
Les fonctions à connaître sont :
Interrompre le flux d’exécution
Comme on l’a vu, si on exécute les commandes :
i=0;
while(i<>10)
disp("coucou");
end
on « bloque » le flux d’exécution dans la boucle while. L’exécution restant dans le bloc indéfiniment,
scilab continue de tourner indéfiniment et est inutilisable. Pour arrêter le flux d’exécution, il faut
alors utiliser le raccourci clavier CTRL+C, L’invite de commande devient alors -1->, on peut alors
tout arrêter en utilisant la commande abort. Cette technique peut aussi être utilisée pour stopper
la commande input. En complément, on peut utiliser la commande halt qui bloque l’exécution tant
qu’une touche n’est pas appuyée, de manière par exemple à laisser le temps de lire sur l’écran.
Pour utilisateurs avancés 15 , on peut utiliser ces fonctionnalités de débogueur en interrompant
volontairement le flux d’exécution avec la commande pause. Une fois le flux d’exécution stoppé, on
peut, par exemple, examiner le contenu des variables pour déterminer la source de l’erreur, puis, soit
relancer le programme avec resume, soit le stopper avec abort.
Par exemple, en utilisant un script contenant :
clear;
i=0;
while (i<>10)
disp("test")
15. Et uniquement eux.
%i
%pi
%e
clear
who
ans
x=real(z)
x=imag(z)
x=conj(z)
x=abs(z)
x=phasemag(z)
sqrt, exp, log
sin, cos, tan
round, floor, ceil
disp("la valeur de x est
"+string(x));)
halt()
x=input("question")
x=input("question",
"string")
lines(0)
save("sauv.sav")
load("sauv.sav")
help fonction
apropos MotCle
Nombre complexe i
Nombre π
Nombre e
Efface toutes les variables
Affiche les variables affectées
Valeur du dernier calcul
Partie réelle d’un nombre complexe z
Partie imaginaire d’un nombre complexe z
Conjugué d’un nombre complexe z
Module d’un nombre complexe z / valeur absolue d’un
nombre réel
Argument en degré d’un nombre complexe
Fonctions racine, exponentielle, et logarithme
Fonctions sinus, cosinus, et tangente
Fonction partie entière approchée, inférieure et supérieure
Affiche la valeur de x est suivie de sa valeur, si x est un réel
Attend l’appui sur une touche, très utile dans un script pour
bloquer l’exécution entre chaque calcul
Affiche la question et stocke la réponse dans la variable x, la
réponse doit être un réel
Affiche la question et stocke la réponse dans la variable x, la
réponse doit être une chaîne de caractère
Permet d’éviter les [More y or n]
Permet de sauvegarder toutes les variables affectées, i.e. l’espace de travail
Permet de restaurer les variables sauvegardées
Aide sur la fonction fonction
Recherche dans l’aide sur le mot clé MotCle
Table 1.1 – Fonctions Scilab à connaître
pause;
end
va arrêter le flux d’exécution au premier affichage de test. L’invite de commande permet alors
de connaître la valeur de i, voire de la modifier avec [10]=return(i);, qui permet de revenir au
programme avec une valeur modifiée de i.
Affichage des résultats Lorsque vous affichez des résultats, Scilab va vous demander More y or
n?. et vous devez appuyer sur y pour en voir davantage, sur n pour ne plus en voir. Pour empêcher ce
comportement, il faut utiliser la commande lines(0);. Attention, le flux d’exécution est alors plus
difficile à stopper.
Application 1 Recherche d’un nombre par essais successifs
Écrire un script qui :
– tire un nombre entier x au hasard, entre 0 et 25. Pour cela, on utilisera l’instruction :
x=round(25*rand(1,1));
Le but est que l’utilisateur trouve, par essais successifs, ce nombre x.
– Le script demande un nombre à l’utilisateur,
– puis affiche « Le nombre ... est supérieur au nombre cherché » ou « inférieur au nombre cherché »
selon les cas,
– et continue ainsi jusqu’à ce que x soit trouvé.
– lorsque c’est le cas affiche « Félicitations, vous avez trouvé en .. essais »
Chapitre 2
Types de données en Scilab
Dans ce chapitre, on va s’intéresser aux types de données que peut manipuler Scilab.
I
I.1
Matrices et vecteurs
Créer des matrices et des vecteurs en Scilab
Donner les coefficients d’une matrice Pour rentrer une matrice en Scilab, on peut rentrer ses
éléments un par un : par exemple : M=[1,2,3;3,2,1];, créera la matrice M :
"
#
1 2 3
M=
.
3 2 1
On voit donc que , permet de changer de colonne et que ; permet de changer de ligne. On peut aussi
remplacer ; par un retour à la ligne, et , par un espace.
Il n’y a pas, par contre, de notion de vecteur : un vecteur est simplement une matrice possédant
une ligne (vecteur ligne), ou une unique colonne (vecteur colonne).
Si Scilab ne sait pas gérer les dimensions, il renvoie le message d’erreur : inconsistent row/column
dimensions.
Commandes sur les matrices Le tableau 2.1 récapitule les commandes à connaître pour la manipulation des matrices et des vecteurs.
I.2
Manipuler les matrices et les vecteurs en Scilab
Initialisation affectation Les matrices peuvent être stockées dans des variables et se manipulent
exactement de la même manière.
En fait en Scilab, toute variable est une matrice. Ainsi, si on définit la variable a par a=2, puis
que l’on fixe la valeur ligne 3, colonne 4 de a comme égale à 5, Scilab « ajoute des 0 » à la variable a
pour en faire une matrice à 3 lignes et 4 colonnes.
Application 1 Si on tape la suite de commandeS : clear;x(5)=3; que contient la variable x ?
25
[n,m]=size(A)
n=size(A,"r")
m=size(A,"c")
m=size(A,"*")
m=length(v)
x=linspace(a,b,n)
x=a:p:y
x=a:y
rand(n,m)
eye(n,n)
ones(n,m)
zeros(n,m)
[ ]
Taille d’une matrice A
Nombre de lignes (row) d’une matrice A
Nombre de colonnes d’une matrice A
Nombre d’éléments d’une matrice A
Nombre d’éléments d’un vecteur v
Construit un vecteur ligne x contenant n points équidistants
entre a et b
Construit un vecteur ligne x qui contient les nombres de a à
b par pas de p.
Idem mais avec un pas de 1 par défaut
Construit une matrice aléatoire de taille n par m
Construit la matrice identité de taille n
Construit une matrice ne contenant que des 1 de taille n par
m
Construit une matrice ne contenant que des 0 de taille n par
m
Matrice vide, permet en particulier d’initialiser sans valeur
Table 2.1 – Manipulation des matrices et des vecteurs.
Opérations mathématiques Les opérations mathématiques se font comme avec des variables
classiques :
– x*M permet de multiplier la matrice M par un scalaire x,
– A*B permet de multiplier deux matrices A et B,
– A+B permet de les additionner,
– A^k permet de calculer Ak , en particulier A^(-1) permet d’inverser 1 la matrice A
– A’ permet de calculer la transposée de la matrice A.
Si les dimensions ne sont pas compatibles, on obtient des messages d’erreur comme : inconsistent
addition, ou inconsistent multiplication.
Enfin, notons que la suite de commandes : A=rand(4,4);A*A^(-1) ne renvoie pas exactement
la matrice identité, mais quelque chose de très proche du fait des erreurs numériques. Il existe aussi
une commande inv(A) pour calculer l’inverse.
Manipulation des éléments, extraction de sous-matrices Pour avoir accès à l’élément ligne
i colonne j, il suffit d’utiliser l’instruction : A(i,j). Ceci est valable en lecture autant qu’en écriture,
i.e. pour modifier la valeur de l’élément qui est dans A. De même, pour un vecteur, la syntaxe est
v(i) pour l’élément i. Attention, le premier élément est le 1, le dernier vaut la taille en ligne/colonne.
Pour extraire une partie de la matrice, par exemple le vecteur des éléments lignes 1 à 3 de la
colonne 2, on utilise : A(1:3,2). Pour extraire la ligne 3, on dispose d’un raccourci : A(:,3), idem
pour la colonne 2 : A(2,:). Par souci de simplicité, un raccourci permet aussi d’obtenir le dernier
élément : A(:,$) est ainsi la dernière colonne, tandis que v($) est le dernier élément de v.
Ces matrices extraites peuvent être bien entendu stockées dans de nouvelles variables.
1. Ne pas oublier les parenthèses autour du -1.
Enfin, comme pour les éléments, cette extraction est valable en lecture comme en écriture. Ainsi,
par exemple, les commandes :
A=rand(4,4); A(1,:)=1:4; A(:,2)=ones(4,1);
permettent de créer une matrice aléatoire, puis de remplacer la première ligne par les entiers de 1 à
4. Enfin, elles remplacent la colonne 2 par des 1.
Ceci peut aussi être utilisé pour supprimer une ligne ou une colonne en affectant la valeur matrice
vide. Par exemple : A(1,:)=[]; supprime la ligne 1 de la matrice A.
Si on essaie de lire un élément qui n’existe pas, Scilab retourne un message d’erreur : invalid
index. Par contre, si on essaie d’écrire sur un élément qui n’existe pas, par exemple si on écrit :
A=rand(4,4); A(5,5)=3;
Scilab ajoute des zéros à la matrice A de manière à pouvoir mettre l’élément (5,5) à 3.
Note: L’extraction de sous-matrice peut même se faire avec une liste d’indices : A=rand(10,10);v=[1,3,5]; w=[4,6];B=A(v,
la variable B contiendra alors les lignes 3 × 2 coefficients obtenus en prenant les éléments des lignes 1, 3 et 5 et
des colonnes 4 et 6.
Changement de taille Pour changer la taille d’une matrice, i.e. organiser les éléments d’une autre
manière, on utilise la commande M=matrix(v,n,m), qui prend en entrée une matrice ou un vecteur v
contenant nm éléments et sort la matrice M de taille n par m contenant les éléments de v rangés en
colonnes.
Exemple:
-->x=1:10;matrix(x,5,2)
ans =
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
-->matrix(x,2,5)
ans =
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Concaténation de matrice/vecteur Pour concaténer des matrices et des vecteurs, on procède
comme si il s’agissait de nombres. Ainsi, pour obtenir la matrice C, constituée de la matrice A audessus de la matrice B, il suffit de faire : C=[A;B]. Tandis que C=[A,B] permettra d’obtenir la matrice
A à gauche de la matrice B.
Exemple: Par exemple, on peut obtenir la matrice :
1

4

A=
7

1
1

à l’aide de la commande :
2
5
8
1
1
3
6
9
1
1
1
0
0
0
0
0
1
0
0
0
0

0

1


0
0

A=[matrix(1:9,3,3)’, eye(3,3);ones(2,3),zeros(2,3)]
Notons que cette fonctionnalité est particulièrement utile lorsqu’on stocke le résultat dans la même
matrice. Par exemple, on utilise : M=[M,x] pour ajouter à la matrice M la valeur de la variable x.
Égalité On peut tester si deux matrices ou deux vecteurs sont égaux avec la commande isequal,
qui renvoie F ou T. Pour comparer élément par élément, on peut utiliser simplement == ou >=, on
obtient alors une matrice de F et de T, qui donne pour chaque élément, si il est égal ou supérieur à
son correspondant.
Opérations non mathématiques Scilab permet de faire des opérations non mathématiques, utiles
dans la pratique pour manipuler rapidement les matrices. On dispose en effet de :
addition matrice/scalaire Si x est un scalaire et M une matrice ou un vecteur, M+x permet d’ajouter
à chaque élément de M la valeur de x, cela correspond donc 2 à M+x*ones(n,m), où n et m sont
la taille de la matrice M.
multiplication élément par élément Lorsqu’on dispose de deux matrices A et B de même taille,
on peut parfois vouloir les multiplier élément par élément. Cela peut être fait par la commande
A.*B qui évite ainsi le passage par une boucle for. Bien entendu, il faut que les tailles soient
compatibles pour que cette opération ait un sens. Pratiquement, l’opération C=A.*B remplace
la suite d’instructions :
[n,m]=size(A);
for i=1:n
for j=1:m
C(i,j)=A(i,j)*B(i,j);
end
end
Fonctions de Scilab Le tableau 2.2 contient une liste des opérations sur les vecteurs/matrices déjà
implémentées dans Scilab. Même si il ne faut pas connaître par cœur ces fonctions, il faut
connaître l’existence de ces fonctions pour gagner du temps, en évitant de les réécrire à chaque
fois. Il faut aussi être capable de retrouver sans erreur la syntaxe exacte en utilisant l’aide et
des exemples. En particulier, attention aux arguments ’c’ et ’r’. Par exemple sum(A,’r’) est
la somme sur les colonnes, le ’r’ signifiant qu’on obtient un vecteur ligne. Attention, la plupart
de ces fonctions sont interdites pour l’option, elles ne sont donc données ici qu’à titre indicatif.
Application de fonctions sur des matrices On peut appliquer toutes les fonctions mathématiques sur des matrices. Dans ce cas, c’est la matrice contenant chacun des éléments qui est renvoyée.
Par exemple, on peut faire :
A=rand(4,4); sin(A);
2. Ceci explique aussi pourquoi en mathématiques, il ne faut pas écrire M + 2 à la place de M + 2I, pour Scilab M+2
n’est pas M+2*eye(2,2), mais M+2*ones(2,2).
qui calcule l’image par la fonction sinus des éléments de A, en évitant ainsi de faire une boucle sur les
éléments.
Ceci est particulièrement utilisé pour les graphiques. Par exemple :
x=linspace(-10,10,100); y=sin(x)+cos(x);
permet d’obtenir un vecteur y contenant l’image par la fonction x 7→ sin(x) + cos(x) de 100 points
équidistants dans l’intervalle [−10, 10]. Ensuite, la commande 3 plot2d(x,y) permettra de dessiner
cette fonction.
max(M)
max(M,’c’)
max(M,’r’)
min(M)
mean(v)
median(v)
st_deviation
sort(v)
sort(M,’c’)
sort(M,’r’)
sortup(v)
sum(v)
sum(A,’c’)
sum(A,’r’)
prod(A)
Maximum d’une matrice M
Maximum sur chacune des lignes
Idem pour les colonnes
Idem pour le minimum
Moyenne
Médiane
Déviation standard
Trie un vecteur par ordre décroissant
Trie chaque ligne de la matrice M.
Idem pour les colonnes
Idem par ordre croissant.
Somme des éléments de v
Somme de chacune des lignes de A
Idem pour les colonnes
Idem pour le produit
Table 2.2 – Fonctions matricielles et vectorielles en Scilab
Application 2
Taper les commandes et expliquer :
A=[1,2,3;4,5,6]
A=[1;2;3;4,5,6] //où est l’erreur?
A=eye(3,3)
A=zeros(4,5)
A=ones(3,2)
A=rand(2,2)
t=1:10
T=0:0.1:3
x=linspace(-10,10,20); //linspace = équirépartis
A=rand(3,4);B=rand(3,4); A+B;
A’ //transposition.
size(A)
size(A,’r’)
size(A,’c’)
3. Voir le prochain chapitre sur les graphiques.
size(A,’*’)
A=rand(3,4); B=[1,1]; A*B //produit
[B,3]
B=[B,B] //concaténation
A*B //pourquoi cela provoque une erreur?
A(1,1)
A(1:3,2)
A(:,3) //: =toutes les lignes /colonnes
A(2,:)
C=A(1:2,3:4) //extraction
A(1:5,6:8) //où est l’erreur?
A(1,1)=0; A //modification d’un élément
A(1,:)=[]
A($,2) //$ donne le dernier élément.
A=rand(3,3);
A=rand(3,3); B=rand(3;3); C= A^(-1)*B; A*C
Application 3
II
Créer deux matrices de taille 3 × 3, puis comparer A.*B et A*B. Expliquer.
Chaînes de caractères
En Scilab, les chaînes de caractères (string en anglais), i.e. les textes, sont des variables comme
les autres.
Les opérations sur ces objets sont simplement :
l’initialisation, obtenue en faisant x="Lundi, Mardi, ";
la concaténation, obtenue en faisant x+y
la comparaison, obtenue en faisant x==y ou x<>y. Par contre x>y n’a pas de sens. Voir plus loin
pour la comparaison à l’ordre lexicographique.
la conversion, d’un réel en chaîne de caractères égale à sa valeur, par la fonction string(x), où x
est une variable contenant un réel.
l’évaluation, est l’opération inverse de la conversion. Elle prend en entrée une expression, par
exemple "x+y" et renvoie le réel obtenu en évaluant cette expression, ici la somme de la variable x et de la variable y. Cette opération est obtenue à l’aide de evstr(c), où c est une
chaîne de caractères.
la longueur d’une chaîne , i.e. le nombre de lettres, est obtenu par la fonction length(c), où c
est une chaîne de caractères.
l’affichage L’affichage à l’écran se fait avec la commande disp. Par exemple : disp("Bonjour").
Cette commande est à conseiller pour afficher un mélange de contenu de variables numériques
et de chaînes de caractères : par exemple : disp("la valeur de x est " + string(x))
L’extraction de sous-chaînes Si x est une chaîne de caractères, alors part(x,i) est le caractère
situé à la position i, tandis que la commande part(x,1:3) renverra les trois premières lettres.
Cela peut être étendu au cas d’un vecteur v contenant des entiers. La commande part(x,v)
renverra les caractères aux indices donnés par v.
La conversion en valeur ascii La conversion ascii permet de coder une lettre en un nombre qui
indique sa position dans la table des caractères. Les 10 chiffres sont codés en premier (de 0
à 9), puis la lettre a est codé en 10, la lettre b en 11, etc. Les lettres majuscules sont codés
avec un chiffre négatif : la lettre A est codé en -10, B en -11 etc. Cette conversion est faite avec
les commandes str2code qui convertit une chaîne en un vecteur de codes, et code2str qui
convertit un vecteur de codes en chaîne. Cela est surtout utilisé pour faire des opérations sur
les chaînes faisant appel à l’ordre lexicographique (ex. décaler d’un certain nombre de lettres,
classer par ordre alphabétique).
Exemple:
x="oui";
//on peut comparer des chaînes de caractères
if (x=="non") then disp("Pourquoi?"); end
//pour séparer la variable x et la chaîne de caractères x on utilise les " "
z=bonjour;//renvoie un message d’erreur
z="bonjour";
length(z)//nombre de lettres
2*z; //renvoie une erreur: on ne peut pas * des chaînes de caractères
x="10";// une chaîne de caractères peut contenir un nombre.
y=2*x;//mais on ne peut pas faire d’opération dans ce cas,
//x ne contient pas la valeur 10 mais la chaîne de caractères 10
y=2*evstr(x);//ici on convertit d’abord x en nombre
disp("la valeur de y est"+y);//erreur car y est un nombre
//on ne peut pas additionner une chaîne de caractères et un nombre.
disp("la valeur de y est"+string(y));
//par contre, on peut concaténer deux chaînes de caractères.
z="bonjour"
x=part(z,1);// x contient "b"
y=part(z,1:3);//y contient "bon"
Enfin, on peut créer des matrices ou des vecteurs contenant des chaînes de caractères. Par exemple,
un carnet d’adresses pourra être représenté par une matrice à 6 colonnes, avec des entrées du type :
["Nom","Prénom","Adresse","Ville","Code postal","Téléphone"];
Chaque ligne représentera une entrée dans le carnet d’adresses, et on ajoutera des entrées avec par
exemple :
M=[M;"Hoche";"Lazare","73 avenue de Saint-Cloud", ...
"Versailles","78000","01.30.84.08.50"];
À noter qu’une telle matrice ne peut pas contenir à la fois des chaînes de caractères et des réels.
Par exemple : x=["test",2] renverra un message d’erreur, d’où l’utilisation de evstr(c) lorsqu’on
a besoin de faire des calculs avec les champs.
Note: Attention à une erreur classique : il ne faut pas utiliser d’apostrophe dans les chaînes de caractères,
qui sont alors confondues avec les ". Par exemple : x="j’aime faire du Scilab"; renverra une erreur.
Application 1
1. Écrire un script qui pose les questions : « Nom ? », puis « Prénom ? », et enfin « Année de
naissance ? » puis affiche : « Bonjour ... agé(e) de .. ans » en indiquant les valeurs rentrées.
2. Écrire un autre script qui :
– demande à l’utilisateur un nombre,
– écrit « Le carré de ... est ... », en remplaçant les points par la valeur rentrée et son carré.
3. Modifier ce script pour qu’il pose à l’utilisateur la question « Voulez-vous continuer ? » et attende
o ou n, toute autre réponse amenant à reposer la question jusqu’à ce que l’une de ces deux
réponses soit entrée.
Utilisation du codage ascii Le codage ascii doit être utilisé dès qu’on fait intervenir l’ordre
lexicographique.
Application 2 Codage César : Le codage César consiste à coder un mot, en décalant sa position
dans l’alphabet d’un paramètre fixé appelé clé. Par exemple, le mot bcpst, avec un clé de 6 sera codé
en hivza.
Cela peut-être fait simplement en remarquant que : str2code(abc) renvoie le vecteur : [10, 11, 12],
tandis que si la variable v vaut [16, 17, 18], on a : code2str(v) renvoie la chaîne de caractères ghi.
– Écrire à partir de ces éléments une fonction prenant en entrée une chaîne de caractères et sortant
une chaîne de caractères codées avec le codage de césar et avec la clé 6.
– Écrire une fonction permettant d’effectuer le décodage.
– Modifier ces fonctions de manière à prendre en entrée la clé.
On ne prendra que des chaînes constituées de lettres minuscules, sans espace.
Application 3 Écrire une fonction estAvant prenant en entrée deux chaînes de caractères a et b,
et sortant un booléen égal à vrai si le mot a arrive avant dans le dictionnaire.

Documents pareils