FAQ MATLAB
FAQ MATLABConsultez toutes les FAQ
Nombre d'auteurs : 11, nombre de questions : 172, dernière mise à jour : 29 septembre 2022
- Comment et pourquoi indenter mon code ?
- Où trouver des informations sur les algorithmes utilisés par MATLAB ?
- Comment exploiter les messages d'erreurs ?
- MATLAB permet-il l'allocation dynamique de mémoire ?
- Qu'est-ce que la préallocation de mémoire ?
- Pourquoi la préallocation de mémoire ralentit-elle mon code ?
- Quelle est la différence entre un script et une fonction ?
- Qu'est-ce qu'un appel fonctionnel ?
- Qu'est-ce que nargin/nargout - varargin/varargout ?
- Qu'est-ce qu'une fonction imbriquée (nested function) ?
- Fonction size : valeur erronée
- Existe-t-il plusieurs types de définitions de variables ?
- Quelle est la durée de vie des variables ?
- Quelle est la différence entre ' et .' ?
- Quelle est la différence entre les opérateurs logiques & et | et les opérateurs logiques && et || ?
- Pourquoi 0.3-0.2-0.1 est-il différent de 0 ?
- Pourquoi les calculs avec des données de type uintX donnent-ils des résultats aberrants ?
- Boucle for : incrémentation
- Qu'est-ce que l'indexage linéaire ?
- Qu'est-ce que l'indexage logique ?
- Comment créer dynamiquement des variables nommées A1, A2, A3… AN ?
- Comment protéger son code ?
- Qu'est-ce qu'un fichier p (p-code) ?
- Que signifie NaN ?
- Qu'est-ce que ans ?
- Comment déterminer approximativement la quantité de mémoire nécessaire pour le stockage d'une variable ?
- Pourquoi MATLAB affiche-t-il des valeurs tronquées ?
- Que représente le symbole @ ?
- Quelle est la signification du symbole tilde « ~ » ?
- Comment effectuer la concaténation chaîne de caractères - valeurs numériques ?
- Comment comparer des chaînes de caractères ?
Avec l'éditeur de MATLAB il est très simple et très rapide d'indenter proprement son code avec le raccourci : CTRL+A (sélection de tout le code) puis CTRL+I (indentation automatique).Il est évidemment aussi possible de le faire par les menus mais cette méthode est la plus rapide.
C'est quoi indenter son code ?
Indenter c'est mettre en forme le code selon certains critères pré-établis. Par exemple, entre un FOR et son END, le code sera décalé d'une tabulation.
À quoi cela peut-il bien me servir ?
Cela permet une meilleure lisibilité du code et par exemple de se rendre assez vite compte qu'il manque un end quelque part. C'est très pratique en particulier depuis l'arrivée des fonctions imbriquées (nested functions) qui nécessitent de bien fermer chaque fonction.
Par exemple, entre ce code (faux) non indenté :
for
i = 1:n
for
j = 2:m
a(i,j) = i*j;
end
Et le même avec indentation :
for
i = 1:n
for
j = 2:m
a(i,j) = i*j;
end
L'erreur saute beaucoup plus aux yeux dans le 2ème code.
L'indentation est donc une aide précieuse surtout lorsque l'on arrive à des codes assez importants avec des boucles et des fonctions imbriquées.
De plus, une fois que vous avez pris l'habitude d'indenter proprement votre code (sachant que l'éditeur le fait quasiment seul) vous verrez que vous aurez beaucoup plus de mal à lire du code non indenté.
La plupart des algorithmes utilisés dans les fonctions sont décrits ou référencés dans la documentation MATLAB (voir le paragraphe Algorithm sur la page de la fonction étudiée).
Cette documentation est disponible sous MATLAB :
- soit en tapant doc dans le Command Window ;
- soit à partir du menu Help > Product Help.
La totalité de la documentation (MATLAB/Simulink + toutes les Toolbox) est également disponible en ligne (voir Où trouver la documentation des différentes version de MATLAB en ligne ?).
Les messages d'erreurs de MATLAB se lisent toujours du bas vers le haut (de la dernière ligne vers la première).
Trois cas de figure sont possibles :
1) L'erreur s'est produite en tapant une commande dans le Command Window.
>> a = sprintf('%f'
,rand(1,2)
??? a = sprintf('%f',rand(1,2)
|
Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.
MATLAB écrit la ligne où l'erreur s'est produite et ajoute un curseur donnant graphiquement la position de l'erreur dans la ligne (ici la place de la parenthèse manquante).
2) L'erreur se produit dans une fonction
Exemple : soit func_A.m
function
func_A
a = sprintf('%f'
,rand(1,2)
Dans le Command Window :
>> func_A
??? Error: File: func_A.m Line: 3 Column: 27
This statement is incomplete.
MATLAB renvoie le nom du fichier où l'erreur s'est produite, le numéro de la ligne dans le fichier et la colonne (approximative) sur cette ligne (équivalent du curseur dans le cas précédent).
3) L'erreur se produit dans des fonctions différentes (plusieurs fichiers m) appelées par la fonction principale.
Exemple : soient trois fonctions func_A.m,func_B.m et func_C.m
function
func_A
func_B
function
func_B
func_C
function
func_C
a = sprintf('%f'
,rand(1,2)
Dans le Command Window :
>> func_A
??? Error: File: func_C.m Line: 3 Column: 27
Expression or statement is incorrect--possibly unbalanced (, {, or [.
Error in ==> func_B at 3
func_C
Error in ==> func_A at 3
func_B
La fonction où l'erreur s'est produite est localisée (en lisant le message de bas en haut) func_A.m => func_B.m => func_C.m. L'analyse de l'erreur s'effectue ensuite comme dans le cas précédent.
Note : lorsqu'un nom de fichier est souligné dans un message d'erreur, il est possible de cliquer dessus dans le Command Window pour l'ouvrir automatiquement à la ligne erronée dans l'éditeur de fichier.
MATLAB ne nécessitant pas la déclaration des variables, l'allocation dynamique de mémoire est donc supportée. Il est alors possible de faire évoluer dynamiquement la taille d'une matrice.
Par exemple :
for
n = 1:5
X(n) = rand;
end
X
Le code ci-dessus renvoie un vecteur X contenant 5 valeurs aléatoires.
Il est également possible de concaténer dynamiquement des valeurs dans une matrice. Pour ce faire, il faut déclarer un matrice vide [] avant la première concaténation.
Par exemple :
X = [];
for
n = 1:5
X = [X rand(1,n)];
end
X
Si, dans le cas de la concaténation, la matrice n'est pas définie vide avant, MATLAB renvoie ce message d'erreur :
??? Undefined function or variable 'X'.
L'allocation dynamique de mémoire est très flexible mais peut rapidement pénaliser la vitesse d'exécution du code (surtout dans le cas de la concaténation). Dans ce cas, on cherchera à optimiser le code en utilisant la préallocation de mémoire.
Sous MATLAB, une matrice ne peut occuper qu'un bloc de mémoire contiguë (non fragmentée).
Lorsque sa taille augmente, MATLAB doit trouver des blocs de mémoire suffisamment grands pour la stocker.
La préallocation de mémoire consiste donc à créer, dès le départ, une matrice à sa taille définitive afin d'accélérer son remplissage en évitant à MATLAB de rechercher ultérieurement des blocs de mémoire disponibles de taille suffisante.
La préallocation s'effectue généralement en utilisant les fonctions zerosDocumentation de la fonction zeros ou onesDocumentation de la fonction ones.
L'exemple suivant est très simple et très théorique. D'autres paramètres doivent bien sûr être pris en compte (complexité du programme, MATLAB JIT, activité des autres programmes). Malgré tout, il met en évidence la nécessité de comprendre la gestion de la mémoire par MATLAB afin d'optimiser ses programmes.
Prenons un exemple simple :
Lors d'une session MATLAB, il ne reste plus en mémoire que trois blocs de mémoire contiguë de taille respective 1 Mo, 2 Mo et 5 Mo. Le code à exécuter crée un vecteur X de taille 1x655360 éléments (655360*8/1024/1024 = 5 Mo) à l'intérieur d'une boucle FOR-END comme ceci :
for
n = 1:655360
X(n) = rand;
end
% Ou
x = [];
for
n = 1:655360
X = [X rand];
end
On peut affirmer que ce code s'exécutera jusqu'à sa fin sans erreur et que X sera bien un vecteur de taille 1x655360.
Regardons la gestion de la mémoire.
Tant que n sera inférieur à 131072 (131072*8/1024/1024 = 1 Mo), MATLAB stockera X dans le bloc de 1 Mo.
À l'itération suivante, le bloc de 1 Mo sera trop petit. MATLAB copiera donc l'intégralité de X dans le bloc de 2 Mo avant de poursuivre les itérations.
Ensuite, tant que n sera inférieur à 262144 (262144*8/1024/1024 = 2 Mo), MATLAB stockera maintenant X dans le bloc de 2 Mo. A l'itération suivante, le bloc de 2 Mo sera trop petit. MATLAB déplacera encore une fois l'intégralité de X dans le bloc de 5 Mo avant de poursuivre les itérations jusqu'à la fin du programme.
Prenons le même exemple, en effectuant la préallocation de X à sa taille définitive avant la boucle FOR-END
X = zeros(1,655360);
for
n = 1:655360
X(n) = rand;
end
Regardons la gestion de la mémoire.
Dès le début du programme, MATLAB cherchera le bloc de mémoire pouvant contenir X=zeros(1,655360); soit le bloc de 5 Mo. On se rend bien compte que MATLAB n'aura plus besoin de déplacer l'intégralité de X durant l'exécution du code. Le code s'exécutera plus rapidement.
Encore une fois, l'exemple précédent est très simple et très théorique. D'autres paramètres doivent bien sur être pris en compte (complexité du programme, MATLAB JIT, activité des autres programmes). Malgré tout, il met en évidence la nécessité de comprendre la gestion de la mémoire par MATLAB afin d'optimiser ses programmes.
Voici un exemple simple chronométré où l'on remarque que la préallocation réduit le temps d'exécution du code :
>> clear X
; tic; for
n = 1:75000, X(n) = rand; end; toc % Sans préallocation
elapsed_time =
11.3590
>> clear X
; X = zeros(1,75000); tic; for
n = 1:75000, X(n) = rand; end; toc % Avec préallocation
elapsed_time =
0.1880
Lien : 1106 - Memory Management Guide
Lien : How do I pre-allocate memory when using MATLAB?
La pré-allocation de mémoire n'est efficace que sur des matrices de tailles suffisantes. Utilisée avec des matrices de petites tailles, sa mise en place peut être plus longue que l'ensemble des affectations des éléments de la matrice.
-
Un fichier fonction est un fichier d'extension .m contenant la définition d'une fonction. Celui-ci doit impérativement commencer par le mot-clé function suivi par une liste des paramètres facultatifs encadrant le nom de la fonction, à laquelle on donnera le même nom que le fichier :
Sélectionnezfunction
[sortie1, sortie2, …] = nomFonction(entree1, entree2, …)Exemples :
-
fichier fonction sans argument d'entrée ni de sortie :
Sélectionnezfunction
nomFonction -
fichier fonction sans argument de sortie :
Sélectionnezfunction
nomFonction(entree1, entree2, …) -
fichier fonction sans argument d'entrée :
Sélectionnezfunction
[sortie1, sortie2, …] = nomFonction
Il est possible de définir plusieurs fonctions au sein d'un même fichier, mais seule la première (principale, du même nom que le fichier) pourra être utilisée extérieurement. Les autres fonctions ne serviront qu'à son bon fonctionnement.
-
-
Un fichier script, de même extension .m, est un fichier contenant du code MATLAB, mais aucune définition de fonction.
Il est simplement appelé par le nom du fichier comme une fonction sans argument d'entré/sortie, et les éventuelles variables créées le sont dans le workspace dans lequel il est appelé.
Pour les versions antérieures à la version MATLAB R2016b, vous ne pouvez pas mélanger les deux, dans le cas contraire vous obtiendrez l'erreur Function definitions are not permitted at the prompt or in scripts.
Dans la pratique on parle de script et de fonction et non pas de fichier script ou fichier fonction.
Il existe deux façons d'appeler une fonction :
-
La syntaxe « ligne de commande » : le nom de la fonction est suivi par les arguments séparés par des espaces :
SélectionneznomFonction arg1 arg2 … argn
Les arguments sont traités comme chaînes de caractères :
SélectionnezfileName =
'monFichier.mat'
; nomFonction fileName% passera la chaîne 'fileName' à la fonction et non 'monFichier.mat'
-
La syntaxe « fonction » : le nom de la fonction est suivi par les arguments mis entre parenthèses et séparés par des virgules :
SélectionneznomFonction(arg1, arg2, …, argn)
Cette deuxième syntaxe, contrairement à la première, permet de rentrer des paramètres variables et de récupérer les sorties de la fonction.
Exemples d'utilisation avec des fonctions utilisant souvent la première syntaxe :
save monFichier.mat X Y
% équivalant à
save('monFichier.mat'
, 'X'
, 'Y'
)
% équivalant à
fileName = 'monFichier.mat'
;
variables = {'X'
, 'Y'
};
save(fileName, variables{:})
load monFichier.mat X Y
% équivalant à
load('monFichier.mat'
, 'X'
, 'Y'
)
% presque équivalant à
S = load('monFichier.mat'
, 'X'
, 'Y'
)
S.X
S.Y
Attention avec l'utilisation de la première syntaxe avec des chemins comportant des espaces :
>> cd C:\mon chemin
% équivaut à passer deux arguments 'C:\mon' et 'chemin'
??? Error using ==> cd
Too many input arguments.
>>
cd 'C:\mon chemin'
% Il faut ajouter les simples quote
% Ou simplement la deuxième syntaxe :
cd('C:\mon chemin'
)
fileName = 'monFichier.jpg'
;
eval(['print -djpeg '
fileName]);
% l'emploi d'eval à éviter devient inutile en utilisant la deuxième syntaxe :
print('-djpeg'
, fileName)
- vararginDocumentation de la fonction varargin : utilisé en dernier paramètre d'entrée d'une fonction, il se présente sous forme d'un tableau de cellules et permet d'avoir un nombre variable d'arguments en entrée. Chaque entrée sera alors contenue dans une cellule de ce tableau.
-
narginDocumentation de la fonction nargin : permet de déterminer le nombre d'entrées d'une fonction :
- utilisé sans argument au sein d'une fonction, il retourne le nombre de paramètres d'entrée passés à cette fonction,
- utilisé avec le nom ou le handle d'une fonction en argument, il retourne le nombre d'entrées que la fonction prend (attention ce nombre est négatif si varargin figure parmi les entrées).
Pour la fonction exemple définie ci-après :
Sélectionnezfunction
exemple(a, b, varargin) nb_entrees = nargin vararginles appels suivants donneront :
Sélectionnez>> exemple(1,2,3,4) nb_entrees = 4 varargin = [3] [4] >> exemple(1,2) nb_entrees = 2 varargin = {} >> nargin(@exemple)
% ou nargin('exemple')
ans = -3
nargin pourra entre autre servir à fournir des valeurs par défaut si le paramètre n'est pas rentré. Exemple :
function
exemple(a)
if
nargin < 1
a = 0;
end
% Reste du code
Lorsque la fonction exemple sera appelée sans aucun argument : exemple(), la variable a aura ici la valeur 0 par défaut.
Symétriquement en sortie nous avons :
- varargoutDocumentation de la fonction varargout : utilisé en dernier argument de sortie, il permet d'avoir un nombre variable de paramètres de sortie. Il est utilisé dans la fonction comme un tableau de cellules, chaque cellule représentant une sortie ;
-
nargoutDocumentation de la fonction nargout : permet de déterminer le nombre de sorties d'une fonction :
- utilisé sans argument au sein d'une fonction, il retourne le nombre de paramètres de sortie demandés par l'appel de cette fonction,
- utilisé avec le nom ou le handle d'une fonction en argument, il retourne le nombre de sorties que la fonction retourne (attention ce nombre est négatif si varargout figure parmi les sorties).
Pour la fonction exemple définie ci-après :
Sélectionnezfunction
[s1, s2, varargout] = exemple nb_sorties = nargout s1 = 1; s2 = 2;if
nb_sorties > 2 varargout{1} = 3;end
if
nb_sorties > 3 varargout{2} = 4;end
les appels suivants donneront :
Sélectionnez>> nargout(@exemple)
% ou nargout('exemple')
ans = -3 >> [a, b, c] = exemple nb_sorties = 3 a = 1 b = 2 c = 3 >> [a, b, d{1:2}] = exemple nb_sorties = 4 a = 1 b = 2 d = [3] [4]
Disponible uniquement à partir de la version R14 7.0.
Une fonction imbriquée (nested function en anglais) est une fonction contenue à l'intérieur d'une autre (mère). Elle offre la possibilité de manipuler les variables déclarées dans la fonction mère, et d'appeler les mêmes fonctions qu'elle. On peut avoir autant de niveaux d'imbrication que l'on souhaite.
- Il faut veiller à ajouter le mot-clé end marquant la fin de toutes les fonctions contenues dans le fichier m.
- La définition d'une fonction imbriquée ne peut pas figurer au sein d'une instruction de contrôle. Ceci inclut les blocs if/elseif/else, switch/case, for, while, et try/catch.
- Une fonction imbriquée doit être appelée directement par son nom (pas d'utilisation de fevalDocumentation de la fonction feval) ou par son handle obtenu grâce à l'opérateur @ (pas d'utilisation de str2funcDocumentation de la fonction str2func).
- Toutes les variables d'une fonction imbriquée ainsi que celles dans laquelle elle est imbriquée doivent être définies explicitement. Aucun script ou fonction (ex. loadDocumentation de la fonction load appelée sans argument de sortie ou assigninDocumentation de la fonction assignin) créant des variables qui n'existent pas déjà dans le workspace des fonctions ne peut être appelé. Voir Variables in Nested and Anonymous Functions.
Une fonction imbriquée peut être appelée depuis :
- la fonction du niveau directement supérieur dans laquelle elle se trouve ;
- une autre fonction imbriquée du même niveau ;
- n'importe quelle fonction imbriquée à l'intérieur de celle-ci.
À moins de faire passer son handle, elle ne sera pas utilisable par une fonction extérieure.
Exemple :
function
fonction_mere
a = 1;
fonction_imbriquee1
fonction_imbriquee2
sous_fonction
% Ne peut pas appeler fonction_imbriquee2_2
function
fonction_imbriquee1
% a peut être lu
b = a + 1;
% Peut utiliser fonction_imbriquee2 de même niveau
fonction_imbriquee2
% Ne peut pas appeler fonction_imbriquee2_2
end
function
fonction_imbriquee2
% Ne peut pas utiliser b contenue dans fonction_imbriquee1
% a peut être changé
a = 2;
fonction_imbriquee2_2
% Peut appeler toute fonction accessible par la fonction mère
sous_fonction
function
fonction_imbriquee2_2
% Peut utiliser a
end
end
% <= end de la fonction_imbriquee2
end
% <= end de la fonction mère
function
sous_fonction
% Ne peut utiliser ni a, ni b
% Ne peut appeler ni fonction_imbriquee1 ni fonction_imbriquee2 ni fonction_imbriquee2_2
end
Vous trouverez un exemple d'utilisation de fonctions imbriquées pour la création d'une interface graphique dans ce tutoriel Développement efficace des interfaces graphiques.
Lien : Nested Functions
Il peut arriver lorsque vous travaillez par exemple avec une image couleur que la fonction sizeDocumentation de la fonction size vous retourne une mauvaise valeur sur la deuxième dimension, pouvant mener à une erreur du style « index out of bounds » ou « index exceeds ». Par exemple pour un image couleur ayant une hauteur de 512 pixels et une largeur de 256 pixels, vous obtiendrez le résultat suivant :
>> size(im)
ans =
512 256 3
>> [height, width] = size(im)
height =
512
width =
768 % au lieu de 256
Ceci vient du fait que vous demandez seulement deux sorties au lieu de trois à la fonction, elle vous renvoie donc le produit des deux dernières dimensions (256 * 3 = 768) sur la seconde sortie, comme l'explique la documentationDocumentation de la fonction size :
[d1,d2,d3,…,dn] = size(X), for n > 1, returns the sizes of the dimensions of the array X in the variables d1,d2,d3,…,dn, provided the number of output arguments n equals ndims(X). If n does not equal ndims(X), the following exceptions hold:
n < ndims(X) di equals the size of the ith dimension of X for 0<i<n, but dn equals the product of the sizes of the remaining dimensions of X, that is, dimensions n through ndims(X).
Ainsi, si vous devez travaillez avec des images couleur (sur trois dimension donc : hauteur x largeur x 3, 3 pour les trois canaux rouge, vert, bleu), n'oubliez pas de demander une troisième sortie à la fonction :
>> [height, width, nb_channels] = size(im)
height =
512
width =
256
nb_channels =
3
% ou si cette valeur ne vous intéresse pas pour la suite de votre programme :
>> [height, width, ~] = size(im)
Cela vous permettra d'éventuellement vérifier par la suite si votre image comporte un seul canal (image en niveaux de gris) ou trois canaux (image couleur).
Notez que vous pouvez aussi demander une dimension particulière à la fonction size :
>> height = size(im, 1)
height =
512
>> width = size(im, 2)
width =
256
>> nb_channels = size(im, 3)
nb_channels =
3
Dans MATLAB, une variable peut être :
- locale ;
- globale ;
- persistante.
Variable locale
Ces variables sont uniquement utilisables dans l'espace de travail où elles ont été définies.
L'espace de travail de base (MATLAB workspace) contient les variables locales créées à partir de l'invite de commandes (MATLAB command prompt) ainsi que celles définies dans les fichiers Script. Les fonctions possèdent leurs propres espaces de travail. Les variables locales créées dans une fonction ne sont visibles que dans cette fonction. Inversement, les variables de l'espace de travail de base (MATLAB workspace) ne sont pas directement visibles dans une fonction.
Aucune syntaxe particulière de définition n'est nécessaire pour les variables locales.
Variable globale
Ces variables sont communes à tous les espaces de travail où elles sont définies.
Il existe deux raisons fondamentales pour éviter d'utiliser ces variables :
- Plusieurs programmes indépendants peuvent utiliser le même nom pour une variable globale. Un programme indépendant peut donc modifier cette variable et entraîner des dysfonctionnements dans les autres programmes. Pour pallier ce problème, on peut préconiser de nommer les variables avec des noms longs suffisamment explicites et d'utiliser une casse en lettres majuscules ;
- La modification du nom de la variable a posteriori, du fait de la déclaration dans chaque programme, peut être très difficile et très périlleuse.
L'utilisation des variables globales doit être évitée. On cherchera plutôt à utiliser les arguments d'entrée/sortie des fonctions ou des variables persistantes si nécessaire.
La définition d'une variable globale doit être précédée du terme globalDocumentation mot clé global dans chacun des espaces de travail où cette variable sera utilisée.
Variable persistante
Les variables persistantes sont des variables locales qui :
- ne peuvent être définies que dans une fonction ;
- ne sont pas détruites à la fin de l'exécution de la fonction.
La définition d'une variable persistante doit être précédée du terme persistentDocumentation mot clé persistent
Les variables créées à partir de l'invite de commandes (MATLAB command prompt) ou dans un fichier Script, existent jusqu'à ce qu'elles soient nettoyées (avec la fonction clearDocumentation de la fonction clear) ou que la session MATLAB soit finie.
Les variables créées à l'intérieur des fonctions existent jusqu'à la fin de l'exécution de la fonction à moins qu'elles ne soient de type persistante ou globale.
Cas particulier : Qu'est-ce qu'une fonction imbriquée (nested function) ? (nested functions - versions R14 7.0 ou supérieures de MATLAB).
Les variables créées dans une fonction sont connues par ses fonctions imbriquées et peuvent donc être modifiées à l'intérieur de celles-ci.
Les opérateurs ' et .' sont tous les deux utilisés pour calculer la transposée d'une matrice.
La différence est que l'opérateur ' calcule la transposée de la matrice conjuguée. Il n'est donc utile qu'avec des matrices à valeurs complexes.
Dans le cas de matrices non complexes, on préférera utiliser l'opérateur .'
>> A = [1 2 ; 3 4]
A =
1 2
3 4
>> A'
ans =
1 3
2 4
>> A.'
ans =
1 3
2 4
>> A = [1+j 1+2j ; 1+3j 1+4j]
A =
1.0000 + 1.0000i 1.0000 + 2.0000i
1.0000 + 3.0000i 1.0000 + 4.0000i
>> A'
ans =
1.0000 - 1.0000i 1.0000 - 3.0000i
1.0000 - 2.0000i 1.0000 - 4.0000i
>> A.'
ans =
1.0000 + 1.0000i 1.0000 + 3.0000i
1.0000 + 2.0000i 1.0000 + 4.0000i
Les opérateurs logiques & et | servent à faire des comparaisons logiques ET et OU.
Les opérateurs logiques && et || sont équivalents aux opérateurs & et |.
Ils sont appelés opérateurs "courts-circuits" car ils permettent d'accélérer le code en diminuant le nombre de tests à effectuer pour valider une combinaison d'opérations logiques.
Prenons le cas d'une opération logique avec deux opérandes.
Avec l'opérateur &, MATLAB détermine la valeur booléenne des deux opérandes avant de faire le ET logique. Alors qu'avec &&, MATLAB commence par déterminer la valeur booléenne du premier opérande et ne teste le second que si le premier a pour valeur VRAI.
L'expression
A & B
revient à faire :
SI (A==VRAI) ET SI (B==VRAI)
…
FIN
alors que l'expression
A && B
revient à faire :
SI (A==VRAI)
SI (B==VRAI)
…
FIN
FIN
Avec l'opérateur |, MATLAB détermine la valeur booléenne des deux opérandes avant de faire le OU logique. Alors qu'avec ||, MATLAB commence par déterminer la valeur booléenne du premier opérande et ne teste le second que si le premier a pour valeur FAUX.
L'expression
A | B
revient à faire :
SI (A==VRAI) OU SI (B==VRAI)
…
FIN
alors que l'expression
A || B
revient à faire :
SI (A==VRAI)
…
SINONSI (B==VRAI)
…
FIN
Lien : Logical Operations
MATLAB, comme tous les autres langages de programmation est confronté à l'imprécision des calculs avec des nombres à virgule flottante.
On peut aisément mettre en évidence cette limitation sous MATLAB en faisant :
>> (0.3-0.2-0.1)==0
ans =
0
>> 0.3-0.2-0.1
ans =
-2.7756e-017
ou encore :
>> a = 0:0.1:1;
>> sprintf('%.20f\n'
,a)
ans =
0.00000000000000000000
0.10000000000000001000
0.20000000000000001000
0.30000000000000004000
0.40000000000000002000
0.50000000000000000000
0.59999999999999998000
0.69999999999999996000
0.80000000000000004000
0.90000000000000002000
1.00000000000000000000
Il est nécessaire d'être particulièrement vigilant lorsque des tests logiques d'égalité sont effectués sur ces nombres.
Le code suivant illustre ce problème :
clc
for
k = 0.1:0.1:0.5
if
k == 0.1
fprintf('\nk est égale à %.1f'
,k);
elseif
k == 0.2
fprintf('\nk est égale à %.1f'
,k);
elseif
k == 0.3
fprintf('\nk est égale à %.1f'
,k);
elseif
k == 0.4
fprintf('\nk est égale à %.1f'
,k);
elseif
k == 0.5
fprintf('\nk est égale à %.1f'
,k);
else
fprintf('\n*** k n''est pas égale à %.1f'
,k);
end
end
MATLAB renvoie :
k est égale à 0.1
k est égale à 0.2
*** k n'est pas égale à 0.3
k est égale à 0.4
k est égale à 0.5
Le problème apparait également avec certaines fonctions comme par exemple findDocumentation de la fonction find :
a = 0:0.1:1;
find(a==0.3)
ans =
[]
Une solution dans ce cas consiste à introduire une tolérance dans le test d'égalité. La valeur de cette tolérance est fonction de l'ordre de grandeur des variables et de la précision de calcul recherchée dans votre problème.
Une version corrigée du code précédent pourrait être :
>> a = 0:0.1:1;
>> tol = 0.01;
>> find(abs(a-0.3)<tol)
ans =
4
Lien : Floating points - IEEE Standard unifies arithmetic model, by Cleve Moler
Lien : Avoiding Common Problems with Floating-Point Arithmetic
Le format uintX (ou unsigned integer X bits) permet de stocker des valeurs entières non signées codées sur X bits. Une variable de ce type ne pourra stocker des valeurs que dans l'intervalle [0 2^X-1] seulement.
Ainsi tout calcul impliquant des variables de ce format visant à sortir de cet intervalle sera faussé.
Exemple pour une simple addition/soustraction :
>> im = uint8([100 200 ; 50 150])
im =
100 200
50 150
>> im(1,1) + im(2,1) % OK : 100 + 50 = 150 compris dans [0 255]
ans =
150
>> im(1,2) + im(2,2) % 200 + 150 = 350 non compris dans [0 255] => on sature à 255
ans =
255
>> im(2,2) - im(1,2) % 150 - 200 = -50 non compris dans [0 255] => on sature à 0
ans =
0
Il faudra le plus souvent caster ces valeurs sous le format single ou double avant d'effectuer les opérations.
>> double(im(1,2)) + double(im(2,2))
ans =
350
Note : on prendra pour habitude de ramener les images dans l'intervalle [0 1] lors du cast vers les types single et double afin de satisfaire la majorité des fonctions de l'Image Processing Toolbox et éviter des résultats inattendus du genre Pourquoi imshow affiche une image toute blanche et/ou noire ?.
Dans MATLAB, une boucle for
se présente la plupart du temps sous la forme :
for
i = valeur_depart : pas : valeur_fin
% …
end
avec un pas de 1 par défaut si celui-ci est omis.
Mais contrairement à d'autres langages, l'incrémentation de la variable itérative (ici i) se fait implicitement, sans avoir à l'écrire. Il est donc incorrect de rajouter i = i + pas; ou i = i + 1; au sein de votre boucle.
Les codes qui suivent, aussi surprenant que cela puisse vous paraître, vont afficher les mêmes valeurs :
Code | Sortie |
---|---|
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
En effet, la variable i aura beau être modifiée au sein de la boucle, cette modification ne sera pas retenue pour l'itération suivante, et i reprendra tout bonnement la valeur suivante dans les valeurs d'entrée 1 : 10. MATLAB vous avertira avec le message :
LOOP index is changed inside of a FOR loop
La seule chose que vous pouvez faire est d'utiliser l'instruction continue
qui passera directement à l'itération suivante.
Si vous souhaitez modifier la variable itérative à votre guise, il vous faudra utiliser une boucle while
à la place :
Code | Sortie |
---|---|
Sélectionnez
|
Sélectionnez
|
Pour accéder à un élément d'une matrice, on emploie la syntaxe suivante :
M = magic(4)
M =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
M(4,3)
ans =
15
En réalité, MATLAB stocke les matrices sous forme de vecteurs colonnes dans la mémoire. Donc dans l'exemple précédent, M sera stockée comme ceci :
16
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1
Ceci a pour conséquence de pouvoir accéder à n'importe quel élément d'une matrice en utilisant un seul index.
Pour récupérer la valeur stockée dans M(4,3), il suffit de faire :
M = magic(4)
M =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
M(12)
ans =
15
La relation de passage entre l'indexage linéaire et l'indexage classique est :
M(i,j)
% est équivalent à :
M(i+(j-1)*size(M,1))
Soit dans l'exemple précédent, M(4,3) <=> M(4+(3-1)*4) <=> M(12)
Cette technique d'indexage est très utile pour vectoriser les codes et ainsi éviter l'utilisation de boucles FOR-END imbriquées. Elle peut être employée avec tous les types de variables : matrices, chaînes de caractères, tableaux de cellules, tableaux de structures ; quelque soit leur dimension.
Note : les fonctions sub2indDocumentation de la fonction sub2ind et ind2subDocumentation de la fonction ind2sub permettent de passer d'une méthode d'indexage à une autre.
Lien : Qu'est-ce que l'indexage logique ?
Lien : Gestion des matricesTutoriel Gestion des matrices
L'indexage des matrices sert à accéder aux éléments qui y sont stockés et il s'utilise comme ceci :
>> X = [4 6 ; 2 3]
X =
4 6
2 3
>> X(1,2)
ans =
6
Il est également possible d'utiliser l'indexage linéaire :
>> X(3)
ans =
6
Il existe une troisième forme d'indexage basée sur les conditions logiques. On la désigne par indexage logique et on l'utilise principalement avec les opérateurs relationnels et les opérateurs logiques. Ce type d'indexage permet d'améliorer l'efficacité des codes en évitant l'utilisation de fonctions supplémentaires (principalement findDocumentation de la fonction find). L'indexage logique est souvent utilisé avec les fonctions anyDocumentation de la fonction any et allDocumentation de la fonction all.
Par exemple, dans le cas précédent, on souhaite trouver toutes les valeurs supérieures à 3, soit 4 et 6.
La méthode classique consisterait à utiliser find comme ceci :
>> X = [4 6
2 3];
>> idx = find(X>3) % Indexage linéaire : on récupère les indices i
% pour lesquels X(i)>3
idx =
1
3
>> X(idx)
ans =
4
6
L'indexage logique consiste simplement à se passer de find :
>> X = [4 6
2 3];
>> idx = (X>3) % Indexage logique : on récupère un tableau logique de même taille
% où une valeur « true » (= 1) correspond à un
% élément vérifiant la condition
idx =
1 1
0 0
>> X(idx) % On sélectionne alors les valeurs pour lesquelles idx est « true »
ans =
4
6
Comparaison en temps d'exécution :
M = rand(5000);
tic
idx = find(M>0.5);
N = M(idx);
toc
elapsed_time =
1.7500
clear idx N
tic
idx = M>0.5;
N = M(idx);
toc
elapsed_time =
1.0470
Lien : Qu'est-ce que l'indexage linéaire ?
Lien : Gestion des matricesTutoriel Gestion des matrices
Oubliez tout de suite cette idée, c'est une très mauvaise pratique qui vous donnera inutilement du fil à retordre et réduira considérablement la lisibilité de votre code !
La bonne méthode consiste à ne créer qu'un seul tableau (numérique ou de cellules selon le cas) de N éléments.
Si les variables sont de même type et de même dimension, il est possible de créer une variable de même type les contenant toutes (concaténation).
-
Par exemple, à la place de créer trois vecteurs A1, A2 et A3 de dimension 1x5 :
SélectionnezA1 = [1 2 3 4 5]; A2 = [1 2 3 4 5]; A3 = [1 2 3 4 5];
il est possible de créer une matrice de dimension 3x5 où chaque ligne correspond à un des vecteurs :
SélectionnezA = [ 1 2 3 4 5 ; 1 2 3 4 5 ; 1 2 3 4 5 ]; A(1,:) A(2,:) A(3,:)
Si les variables sont de type et/ou de dimension différents, il faut utiliser un tableau de cellules.
-
Par exemple, à la place de créer trois vecteurs B1, B2 et B3 de tailles différentes :
SélectionnezB1 = [1 2 3]; B2 = [1 2 3 4]; B3 = [1 2 3 4 5];
il faut créer un tableau de cellules de dimension 1x3 :
SélectionnezB{1} = [1 2 3]; B{2} = [1 2 3 4]; B{3} = [1 2 3 4 5];
Exemple au sein d'une boucle :
SélectionnezN = 10; A_fixe = zeros(N,4);
% préallocation du tableau numérique de taille Nx4
A_varie = cell(N,1);% préallocation du tableau de cellules de N éléments
for
i = 1:N v_fixe = rand(1,4);% exemple de vecteur dont la taille est fixe (4 valeurs)
% => Un tableau numérique de taille Nx4 suffit
A_fixe(i,:) = v_fixe;% Notez les « : » pour sélectionner les 4 éléments de la ligne i
v_varie = 1:i;% exemple de vecteur dont la longueur varie
% => Un tableau de cellules est nécessaire
A_varie{i} = v_varie;% Notez les accolades pour l'indexage
end
Vous avez aussi la possibilité d'utiliser une structure avec des champs dynamiques.
Si vous vous entêtez tout de même dans cette voie, la solution réside dans l'utilisation de la fonction evalDocumentation de la fonction eval, fonction qui est à éviter au maximum :
- perte totale de clarté et de lisibilité du code ;
- perte de performance par la nécessité de réinterpréter à chaque fois la chaîne de caractères argument de eval ;
- complexité de l'analyse du code (fonction appelée, fonction appelante…) ;
- incompatibilité de eval avec le MATLAB Compiler dans les anciennes versions de MATLAB ;
- encombrement du workspace avec un nombre important de variables ;
- obligation de déclarer chacune des variables lors de l'emploi de fonctions imbriquées.
Exemple précédent avec eval - méthode non recommandée !
N = 10;
for
i = 1:N
v = …
eval( sprintf('A%d = v;'
, i) )
end
Lien : Qu'est-ce que la préallocation de mémoire ?
Lien : What Is the EVAL Function, When Should I Use It, and How Can I Avoid It?
Lien : Evading eval, by Loren Shure (blog)
Les 2 scenarii possibles :
- l'utilisateur final a MATLAB alors la commande pcodeDocumentation de la fonction pcode (livrée avec MATLAB) suffit ;
- l'utilisateur n'a pas MATLAB alors il faut utiliser la commande mccDocumentation de la fonction mcc du MATLAB Compiler ou l'interface deploytool.
Lien : Qu'est-ce qu'un fichier p (p-code) ?
Lien : How can I distribute my application and hide my code for users who may or may not have MATLAB?
Lien : Can I depend on the MATLAB Compiler 4.0 (R14) to protect my intellectual property?
Lien : "How do I prevent my P-code from being re-distributed?
Le fichier p (pseudocode pré-analysé) est un fichier généré par la fonction pcodeDocumentation de la fonction pcode à partir d'un fichier m.
Il faut partir de l'exécution des fichiers m (script ou fonction, peu importe) pour mieux comprendre.
Lorsque un fichier m est exécuté, MATLAB vérifie d'abord la syntaxe (pour d'éventuelles erreurs) et transforme ensuite le code lisible (la syntaxe MATLAB) en code machine (binaire). C'est ce dernier code qui est réellement exécuté.
On voit bien que toutes ces opérations influent sur le temps d'exécution du code. Or, pour un fichier m, MATLAB ne fait ces opérations qu'une seule fois. À la deuxième exécution, il se sert du code transformé la première fois (qu'il a stocké en mémoire) et non plus du fichier m.
Un fichier p reprend exactement les mêmes opérations que citées précédemment. L'intérêt premier est donc d'accélérer l'exécution d'un code. Mais ce gain de temps ne sera sensible que si le code n'est exécuté qu'une seule fois.
En pratique, avec les nouvelles versions de MATLAB, ce gain de temps est de moins en moins visible.
Il existe un autre avantage à utiliser des fichiers p. Comme ces fichiers contiennent du code binaire, ils sont (presque) illisibles. Donc, contrairement aux fichier m, on peut cacher le source de son code en générant un fichier p.
Note : pour être plus précis, il y a une différence entre l'exécution d'un script et d'une fonction. Alors que la fonction n'est analysée qu'une seule fois (le code binaire est stocké), MATLAB analyse le script à chaque exécution sans stockage du code binaire.
Le format des fichiers p a changé entre les versions R2007a et R2007b de MATLAB.
Il y a donc incompatibilité descendante à partir cette version.
NaNDocumentation de la fonction NaN est l'acronyme de « Not a Number » que l'on peut traduire par « pas un nombre ».
Cette valeur est attribuée à une variable lors d'une opération qui n'est pas définie numériquement.
Comme par exemple, pour la division de 0 par 0 :
>> a = 0/0
a =
NaN
Le résultat d'une opération arithmétique entre une variable et un NaN donne toujours un NaN :
>> a = 1+NaN
a =
NaN
>> b = 1-NaN
b =
NaN
>> c = 1*NaN
c =
NaN
>> d = 1/NaN
d =
NaN
Remarque : deux variables NaN ne sont pas équivalentes (ceci est conforme à la définition IEEE 754) :
>> a = NaN;
>> b = NaN;
>> a == b
ans =
0
De même :
>> a = [3 NaN NaN 6 3 5 NaN 5 1]
a =
3 NaN NaN 6 3 5 NaN 5 1
>> ua = unique(a)
ua =
1 3 5 6 NaN NaN NaN
Pour savoir si un élément d'un vecteur est de type NaN, il faut utiliser la fonction isnanDocumentation de la fonction isnan :
>> a = [3 NaN NaN 6 3 5 NaN 5 1]
a =
3 NaN NaN 6 3 5 NaN 5 1
>> a == NaN
ans =
0 0 0 0 0 0 0 0 0
>> isnan(a)
ans =
0 1 1 0 0 0 1 0 0
Note : la syntaxe MATLAB est soit NaN, soit nan :
>> a = NaN
a =
NaN
>> a = nan
a =
NaN
>> a = Nan
??? Undefined function or variable 'Nan'.
>>
a = nAn
??? Undefined function or variable 'nAn'.
>>
a = NAn
??? Undefined function or variable 'NAn'.
>>
a = naN
??? Undefined function or variable 'naN'.
>>
a = NAN
??? Undefined function or variable 'NAN'.
Remarque : la fonction NaN peut aussi être utilisée de la même façon que zeros, ones, true, false ou Inf pour obtenir un tableau initial rempli de valeurs NaN :
>> tab = NaN(3,4)
tab =
NaN NaN NaN NaN
NaN NaN NaN NaN
NaN NaN NaN NaN
ans, ou « most recent ANSwer », est une variable créée de façon automatique lorsqu'une instruction retourne un résultat qui n'est affecté à aucune variable. ans garde alors en mémoire cette dernière valeur calculée.
Note : on évitera d'utiliser ans comme variable « normale » dans le code, elle servira essentiellement à effectuer des calculs manuels dans la Command Window.
Notes :
- les formules de calcul données ici sont approximatives. Malgré tout, elles permettent d'obtenir une bonne estimation de la quantité de mémoire nécessaire au stockage des variables sous MATLAB ;
- ces formules ne concernent pas les matrices creuses (sparse matrix) ;
- dans le cas des tableaux de cellules ou des structures, les formules peuvent s'appliquer aux contenus des cellules et/ou des champs (néanmoins le résultat obtenu doit être majoré).
Il existe deux unités pour quantifier la mémoire : l'octet (byte en anglais) et le bit (bit en anglais).
Sur la plupart des machines modernes, l'équivalence entre les deux unités est : 1 octet = 8 bits.
Une variable occupe une certaine quantité de mémoire en fonction de ses dimensions (nombre colonne x nombre de ligne pour un tableau par exemple) et en fonction de sa classe.
La classe par défaut sous MATLAB est la classe Double :
>> x = 1
x =
1
>> class(x)
ans =
double
Une seule valeur en classe Double occupe 64 bits soit 8 octets en mémoire :
>> whos x
Name Size Bytes Class Attributes
x 1x1 8 double
Donc pour déterminer la quantité de mémoire en octets nécessaire au stockage d'une variable de classe Double, il suffit de multiplier ses dimensions par 8.
Par exemple, pour un tableau 100x50x3, la quantité de mémoire nécessaire en classe Double sera :
1000x500x3x8 = 12000000 octets
>> X = rand(1000,500,3);
>> whos X
Name Size Bytes Class Attributes
X 1000x500x3 12000000 double
Pour exprimer cette quantité dans les multiples de l'octet que sont le kilo-octet (ko), le mega-octet (Mo) et le giga-octet (Go), il suffit de diviser par 1024 comme ceci :
1000x500x3x8/1024 = 11719 ko (environ)
1000x500x3x8/1024/1024 = 11.4 Mo (environ)
1000x500x3x8/1024/1024/1024 = 0.011 Go (environ)
Il existe bien entendu d'autres classes de variable. Pour connaître l'espace nécessaire à leur stockage en mémoire, il suffit d'utiliser l'une des formules générales suivantes :
- (dimension1 x dimension2 x dimension3 x … x dimensionN)xf en octets
- (dimension1 x dimension2 x dimension3 x … x dimensionN)xf/1024 en kilo-octets
- (dimension1 x dimension2 x dimension3 x … x dimensionN)xf/1024/1024 en mega-octets
- (dimension1 x dimension2 x dimension3 x … x dimensionN)xf/1024/1024/1024 en giga-octets
Selon les classes les plus courantes disponibles dans MATLAB, f prendra les valeurs suivantes :
Classe | Taille | f |
---|---|---|
uint8, int8, logical | 1 octet / 8 bits | 1 |
uint16, int16, char | 2 octets / 16 bits | 2 |
uint32, int32, Single | 4 octets / 32 bits | 4 |
uint64, int64, Double | 8 octets / 64 bits | 8 |
Par exemple, le tableau 1000x500x3 qui nécessitait 11.4 Mo de mémoire en classe Double nécessitera en classe Single :
1000x500x3x4/1024/1024 = 5.7 Mo (environ)
Lien : Out of memory. Type HELP MEMORY for your options.Erreur Out of Memory
Lien : Gestion des matricesTutoriel Gestion des matrices
Il arrive que l'affichage de valeurs ne semble pas correct dans le Command Window de MATLAB. Lorsqu'il existe une grande variation entre les ordres de grandeur des variables, les valeurs faibles sont semble-t-il arrondies.
Par exemple, si on demande à MATLAB d'afficher le vecteur suivant :
X = [1E-6 1 1E6]
celui-ci affiche :
X =
1.0e+006 *
0.0000 0.0000 1.0000
Les deux premières valeurs sont semble-t-il arrondies à 0.
Il s'agit en fait juste d'un problème d'affichage des valeurs. Celles-ci ne sont en aucun cas arrondies par MATLAB. On peut le vérifier en modifiant la taille des valeurs à afficher avec la fonction formatDocumentation de la fonction format comme ceci :
format long
X = [1E-6 1 1E6]
Ce qui affiche :
X =
1.0e+006 *
0.000000000001000 0.000001000000000 1.000000000000000
ou encore en affichant uniquement la valeur la plus petite :
>> X(1)
ans =
1.0000e-006
Particulièrement utilisé pour des problèmes d'optimisation, dans des fonctions telles que cellfunDocumentation de la fonction cellfun, ou les interfaces graphiques pour attribuer les fonctions callback, l'opérateur @ sert à créer ou accéder à l'identifiant (ou handle) d'une fonction.
1) On peut ainsi se servir de ce symbole pour accéder au handle d'une fonction, et l'utiliser de la même façon :
>> myfun = @sin
myfun =
@sin
>> myfun(pi/2)
ans =
1
2) On peut également s'en servir pour la création de fonctions anonymes :
>> myfun = @(x,y) x.^2 + y.^2
myfun =
@(x,y) x.^2 + y.^2
>> myfun([1 2],[3 4])
ans =
10 20
Cette syntaxe équivaut à créer une fonction telle que
function
r = maFonction(x,y)
r = x.^2 + y.^2;
et prendre son handle comme dans le 1).
3) Il peut servir à faire passer des arguments supplémentaires d'une fonction utilisée comme argument d'entrée d'une autre fonction (pour entrevoir les différentes méthodes : Passing Extra Parameters) :
a = … % paramètre supplémentaire à faire passer
fun = @(x) fonctionAminimiser(x,a);
[x,fval] = fminsearch(fun, x0)
avec
function
f = fonctionAminimiser(x,a)
% f = …
4) Il est aussi possible de créer un handle de fonction à partir d'une chaîne de caractères à l'aide de la fonction str2funcDocumentation de la fonction str2func :
>> myfun = str2func('sin'
)
myfun =
@sin
>> myfun = str2func('@(x,y) x.^2 + y.^2'
)
myfun =
@(x,y) x.^2 + y.^2
Lien : Anonymous Functions
Lien : Create a Function Handle
Outre son utilisation la plus connue sous la forme d'opérateur logique NOT :
>> a = [true, false, false, true]
a =
1 0 0 1
>> ~a
ans =
0 1 1 0
>> a = [32, 16, 0, 7];
>> ~a % équivalent à : a == 0
ans =
0 0 1 0
le symbole « ~ » peut aussi servir depuis la version MATLAB R2009b :
-
dans la définition d'une fonction : à éviter d'avoir une variable inutilisée (et son message d'avertissement rattaché) dans les paramètres d'entrée :
Sélectionnezfunction
ma_fonction(entree1, ~)% code de la fonction
équivalent à
Sélectionnezfunction
ma_fonction(entree1, entree2)% code de la fonction
avec la variable entree2 qui ne sera pas utilisée au sein de la fonction.
Ceci est particulièrement utilisé lors de l'affectation de fonctions anonymes aux propriétés des objets graphiques (cf. Comment utiliser une fonction callback ?) où le second paramètre eventData est rarement utilisé, mais obligatoire pour une fonction callback :
Sélectionnezuicontrol(...
'Style'
,'pushbutton'
,...'String'
,'Tirage :'
,...'Callback'
, @(hObject, ~) set(hObject,'String'
, num2str(rand(),'Tirage : %.2f'
)) ) -
lors de l'appel d'une fonction : à demander la sortie correspondante à la fonction sans toutefois la stocker dans une variable qui ne sera pas utilisée.
Vous n'avez habituellement pas besoin de séparer par une virgule vos paramètres de sortie, mais si vous utilisez ce symbole il vous faudra nécessairement le faire ou vous aurez une erreur de syntaxe.
Sélectionnez[~, sortie2] = ma_fonction();
% suite du code
équivalent à
Sélectionnez[sortie1, sortie2] = ma_fonction();
% suite du code
avec la variable sortie1 qui ne sera jamais utilisée dans la suite du code.
Vous pourriez vous demander à quoi cela peux servir… après tout si l'on ne veut pas une variable, on ne la demande pas. Je vous renvoie alors à ce sujet sur la fonction size, ou au dernier exemple de celui-ci :
Sélectionnez>> nomsPrenoms = {...
'Martin'
,'Durand'
,'Dupond'
;'Jacques'
,'Jean'
,'Paul'
}; >> [~, indices] = sort(nomsPrenoms(1,:));% Nous n'avons besoin que de la seconde sortie
>> nomsPrenoms(:,indices) ans ='Dupond'
'Durand'
'Martin'
'Paul'
'Jean'
'Jacques'
où si l'on ne demande qu'une seule sortie, ce sont les éléments triés (que l'on n'utilise pas) que l'on obtient et non les indices.
Que ce soit pour générer le nom d'un fichier comportant un nombre ou autre, il est souvent utile de pouvoir effectuer une concaténation entre une chaîne de caractères et des valeurs numériques.
Toutefois cette concaténation ne se fait pas directement avec les habituels crochets [] car les deux parties sont des types différents. Or MATLAB stocke ses tableaux sous un unique type.
Ainsi lorsque l'on voudra concaténer une chaîne de caractères (type char) avec une ou plusieurs valeurs numériques (type double, single, uint8…) en utilisant les crochets, seul le type char sera retenu, et les valeurs numériques seront alors castées en char selon leur valeur dans le tableau ASCII, produisant le plus souvent des caractères non imprimables ou inattendus :
>> n = 48;
>> ['fichier_'
n '.txt'
]
ans =
fichier_0.txt
Dans cet exemple, on s'attend à avoir '48'
et non '0'
. Or selon la table ASCII, le caractère '0'
a pour valeur correspondante 48.
>> char(48)
ans =
0
La solution consiste donc à utiliser l'une des fonctions sprintfDocumentation de la fonction sprintf / num2strDocumentation de la fonction num2str :
>> n = 48;
>> sprintf('fichier_%d.txt'
,n)
ans =
fichier_48.txt
>> num2str(n,'fichier_%d.txt'
)
ans =
fichier_48.txt
Note : n étant ici un entier, le format '%d'
est utilisé. Référez-vous à la documentation des fonctions pour l'utilisation de formats et types différents.
Lien : Comment nommer une suite de fichiers : nom_1.ext, nom_2.ext... nom_N.ext ?
Les chaînes de caractères sont représentées sous MATLAB par des vecteurs lignes de type char :
'ma chaîne'
% équivaut à
['m'
, 'a'
, ' '
, 'c'
, 'h'
, 'a'
, 'î'
, 'n'
, 'e'
]
Par conséquent si l'on souhaite effectuer la comparaison entre deux chaînes, ce n'est pas l'opérateur == (fonction eqDocumentation de la fonction eq ; qui donnera une erreur si les chaînes ne sont pas de la même longueur ou un vecteur logique plutôt qu'une seule valeur true/false dans le cas contraire) qu'il faut utiliser mais la fonction strcmpDocumentation de la fonction strcmp (ou strcmpiDocumentation de la fonction strcmpi, strncmpDocumentation de la fonction strncmp et strncmpiDocumentation de la fonction strncmpi selon le type comparaison que l'on souhaite effectuer).
>> 'comparer'
== 'chaînes'
% Chaînes de longueurs différentes
??? Error using ==> eq
Matrix dimensions must agree.
>>
strcmp('comparer'
, 'chaînes'
) % Chaînes de longueurs différentes
ans =
0
>> 'comparer'
== 'comparer'
% Chaînes de mêmes longueurs
ans =
1 1 1 1 1 1 1 1
>> strcmp('comparer'
, 'comparer'
) % Chaînes de mêmes longueurs
ans =
1
Attention : à la différence de la fonction C du même nom, cette fonction renvoie true lorsque les deux chaînes sont égales, et false sinon.
Remarque : cette fonction accepte aussi des tableaux de cellules contenant des chaînes de caractères.
>> noms = {'Durand'
, 'Dupond'
, 'Martin'
};
>> strcmp('Dupond'
, noms)
ans =
0 1 0