Suivant: Graphisme Précédent:Les entrées sorties
Voir: Table des matière
- Index - Accueil
Les fichiers de fonctions ont deux rôles. Ils permettent
à l'utilisateur de définir des fonctions qui ne figurent
pas parmi les fonctions incorporées
de MATLAB (<<
built-in functions >>) et de les utiliser
de la même manière que ces dernières (ces fonctions
sont nommées fonctions utilisateur). Ils sont également un
élément important dans la programmation d'applications
où les fonctions jouent le rôle des fonctions et
procédures des langages de programmation usuels.
On définit la fonction fonc de la manière suivante:
function [vars1, ..., varsm] = fonc(vare_1, ..., varen)
séquence d'instructions
où
Dans l'exemple qui suit, on définit une fonction modulo qui calcule la valeur de a modulo n en prenant pour système de résidus {1, 2, ..., n} au lieu de {0, 1, ..., n-1} (système de résidus considéré par la fonction incorporée mod). Les lignes qui suivent doivent être enregistrées dans un fichier de nom modulo.m.
function [r,q] = modulo(a,n)Les lignes précédées du symbole % sont des lignes de commentaire. Les lignes de commentaire situées entre la ligne function ... et la 1-ere ligne d'instructions sont affichées si l'on demande de l'aide sur la fonction modulo.
% Calcule la valeur de a modulo n en prenant pour systeme de residus
% 1, ... , n au lieu de 0, ... , n-1.
%
% appel : [r,q] = modulo(a,n)
%
% Arguments de sortie :
% r : le residu
% q : le quotient
q = floor(a./n);
r = a - n*q;
% si le reste de la division entiere vaut 0, le residu vaut par convention n
if r == 0, r = n; end
>> help moduloL'appel d'une fonction utilisateur s'effectue de la même façon que l'appel de n'importe quelle fonction MATLAB:
Calcule la valeur de a modulo n en prenant pour systeme de residus
1, ... , n au lieu de 0, ... , n-1.
appel : [r,q] = modulo(a,n)
Arguments de sortie :
r : le residu
q : le quotient
>>
>> b = 10 ; m = 4;
>> [r,q] = modulo(b,m)
r =
2
q =
2
>> modulo(10,5)
ans =
5
>>
La gestion des variables d'entrée et de sortie est très
souple sous MATLAB. Si l'on n'est intéressé que par le
résidu et pas par le quotient, on peut se contenter de ne mettre
qu'une seule variable de sortie, v = modulo(10,4). Dans cet appel la
variable v contiendra le résidu (la première
variable de sortie). Par contre, même si l'on ne souhaite
recueillir que le quotient, on est obligé d'effectuer un appel
de la forme [r,q] =
modulo(10,4) et donc de définir une variable
inutile. Aussi, d'une manière générale, il est bon
de ranger les variables de sortie par ordre <<
d'importance >>. Il est également
possible d'appeler une fonction donnée avec moins de variables
d'entrée que le nombre indiqué pour la définition
de la fonction (il faut bien entendu que le corps de la fonction soit
programmé de sorte de prévoir cette
éventualité). Il existe deux fonctions MATLAB
utiles pour gérer cette situation: nargin qui retourne le nombre de
variables d'entrée utilisés lors de l'appel et nargout qui
retourne le nombre de variables de sortie prévues lors de
l'appel. Voici un petit exemple venant illustrer ces
possibilités.
function [A,rang] = matale(T,m,n)Dans cet exemple, on gère les variables d'entrée de la fonction de sorte de ne pas avoir besoin de donner lors de l'appel le nombre de lignes et de colonnes si la matrice est carrée. On gère aussi les variables de sortie afin de ne pas calculer le rang de la matrice si aucune variable de sortie pour le résultat n'est prévue lors de l'appel.
% Construit une matrice A de m lignes et n colonnes ayant des elements
% entiers generes de maniere aleatoire entre 0 et T.
% Calcule le rang de la matrice si l'appel est effectue avec 2 arguments
% de sortie.
% Si la matrice est carree, le parametre n peut etre omis.
%
% Appels:
% [A,r] = Matale(T,m,n)
% [A,r] = Matale(T,m)
% A = Matale(T,m,n)
% A = Matale(T,m)
if nargin == 2
A = fix(T*rand(m));
else
A = fix(T*rand(m,n));
end
if nargout == 2
rang = rank(A);
end
>> [A,r] = matale(20,3,4)
A =
16 13 13 10
10 16 7 14
4 0 16 8
r =
3
>> [A,r] = matale(20,3)
A =
12 0 18
5 14 9
3 8 8
r =
3
>> A = matale(20,3)
A =
8 7 2
17 16 4
1 0 3
>>
Un point important concerne la gestion des variables entre le programme
principal (ou le workspace) et les fonctions de l'utilisateur. Toutes
les variables définies à l'intérieur d'une
fonction sont des variables locales
à cette fonction. La communication avec des variables du
programme principal (ou du workspace) ou avec des variables d'autres
fonctions se fait uniquement par les variables d'entrée et
sortie de la fonction. Une alternative existe toutefois: il est
possible de déclarer certaines variables comme des variables globales . Une
variable globale peut être partagée entre un programme
principal et plusieurs fonctions sans qu'il soit besoin de la
spécifier parmi les variables d'entrée-sortie des
différentes fonctions. On déclare une variable globale
grâce au mot clé global. Par exemple pour
déclarer la variable numex globale on écrit global numex.
Attention, la déclaration global numex doit être reprise
dans
chaque fonction utilisant numex comme variable.
== | : | égal à (x == y) |
> | : | strictement plus grand que (x > y) |
< | : | strictement plus petit que (x < y) |
>= | : | plus grand ou égal à (x >= y) |
<= | : | plus petit ou égal à (x <= y) |
~ = | : | différent de (x ~ = y) |
Les opérateurs logiques sont:
& | : | et (x & y) |
| | : | ou (x | y) |
~ | : | non (~ x) |
Les opérateurs de comparaison et les opérateurs logiques sont utilisés essentiellement dans les instructions de contrôle, voir le paragraphe 5.3.
Syntaxe :
séquence d'instructions
end
où
borne_inf etborne_sup sont deux constantes réelles (appelées paramètres de la boucle);
séquence d'instructions est le traitement à effectuer pour les valeurs d'indices variant entre borne_inf et borne_sup avec un incrément de 1. On parle du corps de la boucle.
Interprétation :
Si borne_inf est plus petit
ou égal àborne_sup, le traitement séquence d'instructions est
exécuté borne_sup - borne_inf fois,
pour les valeurs de la variable indice
égales à borne_inf, borne_inf+1, ..., borne_sup. Si borne_inf est
strictement plus grand que borne_sup,
on passe à l'instruction qui suit immédiatement
l'instruction de fin de boucle (end).
Remarque :
L'indice de boucle ne prend pas nécessairement des valeurs
entières. D'autre part il n'est pas nécessaire que
l'indice de la boucle apparaisse dans le corps de la boucle; par contre
il est interdit de modifier sa valeur s'il apparaît. Il est
possible d'imbriquer des boucles mais elles ne doivent pas se
recouvrir. On peut utiliser un incrément (pas) autre que 1 (valeur par
défaut). La syntaxe est alors borne_inf: pas : borne_sup.
Le pas peut être négatif. Attention à bien
gérer la borne supérieure! Voici un exemple (idiot)
venant illustrer les possibilités de variations de l'indice de
la boucle
>> for r=1.1:-0.1:0.75Voici un exemple d'utilisation d'une boucle pour calculer n! (le lecteur attentif sait calculer n! plus simplement ... par exemple en exécutant prod([1:n])).
disp(['r = ', num2str(r)]);
end
r = 1.1
r = 1
r = 0.9
r = 0.8
>>
>> n = 4;
>> nfac = 1;
>> for k = 1:n
nfac = nfac*k;
end
>> nfac
nfac =
24
>>
Syntaxe :
séquence d'instructions
end
où
Interprétation :
Tant que expression logique est
vraie le traitement séquence
d'instructionsest exécuté sous forme d'une
boucle. Lorsque expression logique
devient faux, on passe à l'instruction qui suit
immédiatement l'instruction de fin de boucle (end).
Remarque :
expression logique est en
général le résultat d'un test (par exemple i < Imax) ou
le résultat d'une fonction logique (par exemple all(x)). Il
est
impératif que le traitement de la séquence
d'instructions agisse sur le résultat de expression logique sans quoi on boucle
indéfiniment (-:.
Voici comment calculer n! avec une boucle while:
>> n = 4;
>> k = 1; nfac = 1;
>> while k <= n
nfac = nfac*k;
k = k+1;
end
>> nfac
nfac =
24
>>
L'instruction conditionnée la plus simple a la forme suivante:
Syntaxe :
séquence d'instructions
end
où
Interprétation:
la séquence d'instructions
n'est exécutée que si le résultat de
l'évaluation de l'expression logique
est vraie (c'est-à-dire vaut 1). Dans le cas contraire on
exécute l'instruction qui suit le mot clé end. Dans le
cas où l'expression logique
est vraie, après exécution de la séquence
d'instructions on reprend le programme à
l'instruction
qui suit le mot clé end.
Remarque :
Contrairement à certains langages de programmation, il n'y a pas de mot clé <<
then >> dans cette instruction
conditionnée. Notez également que la marque de fin de
bloc conditionné est le mot clé end
et non pas<<
endif >>.
Il existe une séquence conditionnée sous forme d'alternatives:
Syntaxe :
ifexpression logique
séquence d'instructions 1
else
séquence d'instructions 2
end
où
Interprétation :
Si expression logique est vraie la
séquence d'instructions 1
est
exécutée, sinon c'est la séquence
d'instructions 2 qui est exécutée. Le
déroulement du programme reprend ensuite à la
première instruction suivant le mot clé end.
Il est bien entendu possible d'imbriquer des séquences
d'instructions conditionnées (au sens où la
séquence d'instruction conditionnée contient des
séquences d'instructions conditionnée). Pour une
meilleure lisibilité, il est recommandé d'utiliser des
indentations afin de mettre en évidence l'imbrication des
séquences d'instructions conditionnées.
Il est possible d'effectuer un choix en cascade:
Syntaxe :
ifexpression logique 1
séquence d'instructions 1
elseif expression logique 2
séquence d'instructions 2
...
elseif expression logique N
séquence d'instructions N
else
séquence d'instructions par défaut
end
Interprétation :
Si expression logique 1 est vraie
la séquence d'instructions 1 est
exécutée et le programme reprend ensuite à la
première instruction suivant le mot clé end, sinon si expression logique 2 est vraie la séquence d'instructions 2 est
exécutée et le programme reprend ensuite à la
première instruction suivant le mot clé end, etc. Si aucune des
expressions logiques 1 à N n'est vraie alors séquence d'instructions par défaut
est exécutée.
Remarque :
Attention à ne pas laisser
d'espace entre else et if; le mot clé est elseif.
On utilise fréquemment un choix en cascade lors d'initialisation de données. Par exemple, on initialise une matrice A en fonction de la valeur d'une variable numex (numéro d'exemple) de la manière suivante:
if numex == 1
A = ones(n);
elseif numex == 2
A = magic(n);
elseif numex == 3 | numex == 4
A = rand(n);
else
error('numero d''exemple non prevu ...');
end
Syntaxe :
casecst1,
séquence d'instructions 1
casecst2,
séquence d'instructions 2
...
casecstN,
séquence d'instructions N
otherwise
séquence d'instructions par défaut
end
où
Interprétation :
Si la variable var est
égale à l'une des constantes cst1,
..., cstN, (par
exemple csti) alors
la séquence d'instructions correspondante (ici séquence d'instructions i) est
exécutée. Le programme reprend ensuite à la
première instruction suivant le mot-clé end. Si la variable var n'est égale à aucune des
constantes la séquence d'instructions
par défaut est exécutée.
Remarque :
La variable var doit bien
entendu
être du même type que les constantes cst1, ..., cstN.
Il n'est pas nécessaire de prévoir un cas par
défaut (bien que cela soit préférable). S'il n'y a
pas de cas par défaut et si la variable var n'est égale à aucune des
constantes, alors le programme continue à la première
instruction suivant le mot-clé end.
Il est possible de regrouper plusieurs <<
cas >> si la séquence
d'instructions
à exécuter est la même pour ces différents
cas. La syntaxe est alors,
case{ cstk , cstl , ...}
séquence d'instructions commune
Reprenons l'exemple où l'on souhaite initialiser une matrice A en fonction de la valeur prise par une variable numérique numex (numéro d'exemple). En utilisant un choix ventilé on obtient:
function A = initA(n,numex)Voici un exemple de choix ventilé portant sur une variable de type chaîne de caractères.
switch numex
case 1,
A = ones(n)
case 2,
A = magic(n);
case {3,4},
A = rand(n);
otherwise
error('numero d''exemple non prevu ...');
end
rep = input('Votre reponse (oui, non, chepas) :');
switch rep
case {'oui','o'},
disp('bravo ...');
case {'non','n'}
disp('perdu ...');
case 'chepas'
disp('c''est pourtant facile ...');
end
L'instruction errorpermet
d'arrêter un programme et d'afficher un message d'erreur. La
syntaxe est error('
message d''erreur '). L'instruction warning permet d'afficher un message
de mise en garde sans suspendre l'exécution du programme. La
syntaxe est warning('
message de mise en garde '). Il est possible d'indiquer
à MATLAB de ne pas afficher les messages de mise en garde d'un
programme en tapant warning off
dans la fenêtre de commandes. On rétablit l'affichage en
tapant warning on.
On peut ainsi améliorer la fonction matale de la manière suivante:
function [A,rang] = matale(T,m,n)On obtient alors les messages suivants:
% Construit une matrice A de m lignes et n colonnes ayant des elements
% entiers generes de maniere aleatoire entre 0 et T.
% Calcule le rang de la matrice si l'appel est effectue avec 2 arguments
% de sortie.
% Si la matrice est carree, le parametre n peut etre omis.
%
% Appels:
% [A,r] = Matale(T,m,n)
% [A,r] = Matale(T,m)
% A = Matale(T,m,n)
% A = Matale(T,m)
% si la fonction est appelee avec un nombre d'arguments d'entree
% different de 2 ou 3, on arrete tout ...
if nargin ~= 2 & nargin ~= 3,
error(' La fonction matale doit avoir 2 ou 3 arguments d''entree ');
end
if nargin == 2
A = fix(T*rand(m));
else
A = fix(T*rand(m,n));
end
if nargout == 2
rang = rank(A);
if nargin == 2,
rangx = m;
else
rangx = min([m,n]);
end
if rang ~= rangx, warning(' Le rang n''est pas maximum '); end;
end
>> A = matale(3);La commande pause permet d'interrompre l'exécution du programme. L'exécution normale reprend dès que l'utilisateur enfonce une touche du clavier. L'instruction pause(n) suspend l'exécution du programme pendant n secondes.
??? Error using ==> matale
La fonction matale doit avoir 2 ou 3 arguments d'entree
>> A = matale(20,3)
A =
8 18 8
12 14 18
15 3 18
>> [A,r] = matale(20,3)
Warning: Le rang n'est pas maximum
> In /home0/maths/balac/DOCMATLAB/matale.m at line 34
A =
1 4 3
10 15 11
3 12 9
r =
2
>>
Notons l(x) le numéro de la ligne et c(x) le numéro de la colonne du carré sur lequel se trouve l'entier x. Partant d'un carré d'ordre impair n=2k+1, la technique de Moschopoulos peut se formuler comme suit:
si x n'est pas un multiple de n, alors
l(x+1) = 1 + l(x) modulo(n)
c(x+1) = 1 + c(x) modulo(n)si x est un multiple de n, alors
l(x+1) = 2 + l(x) modulo(n)
c(x+1) = c(x) modulo(n)
Dans ces règles pour la prise du modulo, le système de
résidus que l'on considère est 1, 2, ..., n et
non pas 0, 1, ..., n-1.
La fonction magik met en oeuvre la méthode de Moschopoulos.
function M = magik(n)La fonction utilise la fonction pos. Cette dernière fonction peut soit être écrite à la suite de la fonction magik si l'on dispose de la version 5 de MATLAB (dans ce cas il s'agira d'une sous-fonction qui ne sera visible que de la fonction magik) soit être sauvegardée dans un fichier pos.m.
%
% Calcule le carre magique d'ordre n selon la methode
% de Moschopoulous.
%
% Entree:
% n : ordre du carre (entier impair)
% Sortie:
% M : le carre magique
%
if rem(n,2) == 0,
msg = ['la methode de Moschopoulous ne construit que des carres' ...
,' d''ordre impair'];
error(msg)
end
k = (n-1)/2;
l(1) = k+2;
c(1) = k+1;
M(l(1),c(1)) = 1;
for x = 2:n.^2
[l(x),c(x)] = pos(x-1,l(x-1),c(x-1),n);
M(l(x),c(x)) = x;
% ou plus simplement M(pos(x,l(x-1),c(x-1))) = x;
end
function [ly,cy] = pos(x,lx,cx,n)
%
% Retourne la position (indice de ligne ly et indice de colonne cy)
% dans le carre magique d'ordre n de l'entier y = x+1 selon la
% regle de Moschopoulous.
%
% Entree:
% n : ordre du carre (entier impair)
% x : l'entier considere
% lx : indice de ligne de l'entier x dans le carre magique
% cx : indice de colonne de l'entier x dans le carre magique
%
% Sortie:
% ly : indice de ligne de l'entier y=x+1 dans le carre magique
% cy : indice de colonne de l'entier y=x+1 dans le carre magique
%
if rem(x,n) == 0
ly = modulo(2+lx,n);
cy = modulo(cx,n);
else
ly = modulo(1+lx,n);
cy = modulo(1+cx,n);
end
Voici quelques exemples d'utilisation de la
fonction magik. On vérifie que la somme des
éléments des différentes lignes ainsi que la somme
des éléments des différentes colonnes sont bien
constantes. Pour calculer la somme des éléments diagonaux
c'est un peu plus compliqué. On remarque que le carré
magique construit diffère du carré magique
retourné
par la fonction MATLAB incorporée magic.
>> magik(4)
??? Error using ==> magik
la methode de Moschopoulous ne construit que des carres d'ordre impair
>> magik(5)
ans =
11 24 7 20 3
4 12 25 8 16
17 5 13 21 9
10 18 1 14 22
23 6 19 2 15
>> sum(magik(5),1)
ans =
65 65 65 65 65
>> sum(magik(5),2)
ans =
65
65
65
65
65
>> magic(5)
ans =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
Suivant: Graphisme Précédent:Les entrées sorties
Voir: Table des matière
- Index - Accueil
(c) Stéphane Balac - Centre de Mathématiques - INSA de Lyon