Documente Academic
Documente Profesional
Documente Cultură
Cuprins
Introducere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Utilizarea efectivă a script-urilor . . . . . . . . . . . . . . . . . . . . . 2
Funcţii şi spaţiul de lucru . . . . . . . . . . . . . . . . . . . . . . . . . 3
Condiţionale: if şi switch . . . . . . . . . . . . . . . . . . . . . . . . . 4
Cicluri for şi while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Debugging şi profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Function handles şi funcţii anonime . . . . . . . . . . . . . . . . . . . . 8
Subfuncţii şi funcţii imbricate . . . . . . . . . . . . . . . . . . . . . . . 10
Erori şi avertismente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Argumente de intrare şi iesire, precizări suplimentare . . . . . . . . . . 12
Introducere
Un fişier M este un fişier text ce conţine comenzi MATLAB şi care are tipul .m .
Există două tipuri, script şi function. MATLAB are încorporat un foarte bun
editor, el se poate lansa din meniu sau tastând edit . Totuşi, utilizatorul poate
utiliza orice editor de texte. Pentru a putea fi executat, un fişier M trebuie salvat
pe calea curentă (path). Calea este o listă de directori (foldere) în care MATLAB
caută fişiere. Utilizaţi addpath sau meniuri pentru a vizualiza sau modifica
calea. Nu este nevoie să compilăm un fişier M. Pentru execuţie este suficient să
tastăm numele fişierului (fără extensie). Modificările care sunt salvate pe disc
vor fi luate în considerare la urmatorul apel al funcţiei sau script-ului. Un tip
important de instrucţiune într-un fişier M este comentariul, indicat printr-un
semn procent %. Orice text din linia curentă situat după semnul procent este
ignorat, exceptând situaţia când el este parte a unui şir de caractere. Mai mult,
primul bloc contiguu de comentarii dintr-un fişier M serveşte ca documentaţie
pentru fişier şi va fi afişat în fereastra de comandă dacă se dă help pe fişier. De
exemplu, să presupunem că textul de mai jos este salvat în fişierul cu numele
myscript.m pe calea curentă:
1
help myscript
Un exemplu aiurit
de fisier .m
%%
% A Hilbert matrix has entries that are reciprocals of
% integers.
%%
%
% $$H=(h_{ij}), h_{ij}=\frac{1}{i+j-1}$$
%
format rat
H = hilb(4)
%%
% Although the inverse of a Hilbert matrix is difficult
% to find numerically by Gaussian elimination, an explicit
% formula is known.
invhilb(4)
%%
format short e
H*ans
2
În plus, celulele vă permit să creaţi secţiuni cu titluri şi cu cuprinsuri (table
of contents) cu hyperlink-uri. Editorul propriu al MATLAB este cel mai bun
mod de a publica script-uri. El va ajută să creaţi celule, să lucraţi cu ele,
să evidentiati cu claritate marginile de celule şi titlurile şi să publicaţi şi să
vizualizaţi rezultatele cu bătaie de cap minimă. Ca regulă utilă, apelati script-
urile doar din linia de comandă şi nu apelaţi alte script-uri dintr-un script.
Pentru a scrie programe mai mari şi a rezolva subproblemele într-un cadru mai
larg, funcţiile sunt o alegere mai bună.
3
x2 = (-b - d) / (2*a);
[r1,r2] = quadform(1,1,1)
r1 =
-5.0000e-01 + 8.6603e-01i
r2 =
-5.0000e-01 - 8.6603e-01i
Condiţionale: if şi switch
Adesea, o funcţie trebuie să se ramifice pe baza unei condiţii întâlnite la execuţie.
MATLAB oferă facilităţi de acest tip similare celor din multe alte limbaje de
programare.
Iată un exemplu ce ilustrează cele mai multe facilităţi ale instrucţiunii if.
if isinf(x) || ~isreal(x)
disp('Bad input!')
y = NaN;
elseif (x == round(x)) && (x > 0)
y = prod(1:x-1);
else
y = gamma(x);
end
4
mai sugestiv decât “ if x ” când x este numeric. O atenţie specială necesită
utilizarea tablourilor la construcţia condiţiilor dintr-o instrucţiune if. Dacă
condiţia nu este scalară, se consideră adevarată numai dacă toate elementele ei
sunt adevarate/nenule. Pentru a evita confuziile, este cel mai bine să se utilizeze
any ori all pentru a reduce tablourile logice la valori scalare.
Condiţiile scalare compuse se pot crea utilizând operatorii && (şi logic) şi ||
(SAU logic) în locul operatorilor tablou & şi | . (Operatorul NOT ~ este identic
în ambele cazuri.) Operatorii dublu-simbol pot fi scurt-circuitaţi: dacă, pe
masură ce o condiţie este evaluată de la stânga la dreapta, devine clar înainte
de terminarea evaluării ce valoare finală se va obţine, atunci evaluarea condiţiei
este oprită. Aceasta facilitate face convenabilă scrierea unor construcţii ca
care altfel ar conduce la erori sau ar fi dificil de scris. În unele situaţii, funcţia
isequal este mai robustă decât operatorul relaţional ==. De exemplu, con-
strucţia isequal(s,’foo’) returnează false dacă s nu este identic cu şirul ’foo’
, pe când s==’foo’ va da o eroare dacă s nu are dimensiunea 1×3. De obicei,
prima comportare este mai de dorit. Construcţia if/elseif este de preferat
numai când avem un număr mic de alternative. Dacă avem un număr mare de
opţiuni se preferă switch. De exemplu:
switch units
case 'length'
disp('meters')
case 'volume'
disp('liters')
case 'time'
disp('seconds')
otherwise
disp('I give up')
end
Expresia din switch poate fi un şir sau un număr. Expresia din case poate fi
un scalar, un şir, un tablou de celule. Se execută secvenţa de comenzi din primul
case care se potriveşte cu expresia din switch. Execuţia nu curge mai departe
ca în C. Dacă otherwise este prezent, secvenţa de comenzi corespunzătoare se
execută dacă nu avem nici o potrivire.
5
f = [1 1];
for n = 3:10
f(n) = f(n-1) + f(n-2);
end
x = 1:100; s = 0;
for j = find(isprime(x))
s = s + x(j);
end
calculează suma numerelor prime mai mici decât 100. O versiune mai bună:
ans =
25
ans =
1060
Condiţia este evaluată înainte de execuţia corpului, deci este posibil să avem
zero iteraţii. Uneori este o idee bună să limităm numărul de iteraţii pentru a
evita ciclurile infinite (cum s-ar putea întâmpla mai sus dacă x este infinit).
Aceasta se poate face în mai multe feluri, dar cel mai comun este utilizarea lui
break.
6
n = 0;
while abs(x) > 1
x = x/2;
n = n+1;
if n > 50, break, end
end
Debugging şi profiling
7
profiling , care ţine evidenţa timpului petrecut cu execuţia fiecărei linii dintr-
o funcţie. Profiling este de asemenea un mod de a vedea dependenţele dintre
funcţii (cine pe cine apelează). Se începe prin a tasta profile viewer .
fzero(@sin,3)
ans =
3.1416e+00
8
Acum sincos este o funcţie de o variabilă, iar apelurile sincos(pi/4) şi
sincos(rand(2)) sunt perfect acceptabile. La fel, se pot crea şi funcţii anonime
de mai multe variabile, ca în exemplul
w = @(x,t,c) cos(x-c*t);
ans =
-7.8540e-01
f = @(x) bigfun(0.5,x,b_value);
ans =
5.6714e-01
ans =
5.2124e-01
9
ans =
4.8391e-01
ans =
4.5278e-01
ans =
4.2630e-01
Linia cu end este opt, ională în fişierele care cont, in o singură funcţie, dar este
o idee bună cand apar mai multe funcţii şi este obligatorie la utilizarea funcţiilor
imbricate. Schimbările făcute asupra lui a , b , sau c in interiorul lui discrim
nu se vor propaga în restul quadform , nici o altă variabilă din funcţia primară
nu va fi disponibilă în discrim . Subfuncţiile nu sunt vizibile înafara fişierului
de definit, ie —doar funcţia primară poate fi apelată. Totus, i există o except, ie
majoră şi utilă la această regulă. Presupunem că dorim să investigăm valorile
proprii ale unei anumite matrice A(x) —concret, dorim să găsim cel mai mic x
astfel încât partea reală maximă a valorilor proprii să fie egală cu 1. O abordare
simplă este sa utilizăm fzero pentru a atinge valoarea dorită:
10
function x0 = findx
x0 = fzero(@objective,[0 10]);
end
function r = objective(x)
B = diag(ones(499,1),1); A = B-B';
A(1,1) = x;
e = eig(A); r = max(real(e)) - 1;
end
Subfuncţia objective este transmisă ca un handle lui fzero, care este capabilă
să acceseze şi să apeleze subfuncţia, chiar dacă fzero ar putea să nu o recunoască
dacă ar fi apelată direct prin nume.
O funcţie imbricata (nested function) este similara cu o subfuncţie, dar
este definita în interiorul domeniului de vizibilitate al funcţiei părinte. Ea se
comporta diferit de o subfuncţie dintr-un punct de vedere foarte important:
spat, iul de lucru se poate suprapune peste cel al părintelui. Orice variabilă
utilizată atât în funcţia imbricată, cât şi în funcţia părinte este partajată.
Unul din motivele utilizării funcţiilor imbricate este crearea de efecte colat-
erale persistente. Să consideram din nou exemplul de mai sus cu valorile pro-
prii. Deoarece fzero este o “cutie neagra” cu sintaxa standardizată, ea poate
returna doar valoarea x pe care o căutăm. Nu ne poate spune, de exemplu,
partea imaginară a valorii proprii a cărei parte reală este 1, nici nu ne poate
da altă informat, ie despre valorile proprii. Pentru a obt, ine acele funcţii, trebuie
sa repetăm mult din funcţia objective, ceea ce face codul confuz şi necesită
timp de calcul suplimentar. Reorganizând calculele prin utilizarea unei funcţii
imbricate, se pot transmite informat, ii suplimentare înafara objective :
function x0 = findx
function r = objective(x)
A(1,1) = x;
e = eig(A); r = max(real(e)) - 1;
end
B = diag(ones(499,1),1); A = B-B';
e = []; % create a shared variable for side effect
x0 = fzero(@objective,[0 10]);
plot(e,'x')
end
11
poate conduce la cod care es, ueaza us, or şi este dificil de citit şi înteles. Există,
totus, i, situat, ii în care astfel de tehnici sunt efectiv avantajoase.
Erori şi avertismente
Funcţiile MATLAB pot întâlni instruct, iuni imposibil de executat, într-un mod
care nu poate fi anticipat până la execut, ia efectivă. De exemplu, instruct, iunea
A*B este sintactic validă, dar nu are sens dacă matricele au dimensiuni incom-
patibile. Într-o astfel de situat, ie se declans, ează o eroare: execut, ia se opres, te,
se afis, eaza un mesaj, iar controlul se dă în fereastra de comandă (la prompter),
argumentele de ies, ire fiind ignorate. Se pot declans, a erori în funcţiile scrise de
dumneavoastră cu instructiunea error, apelata cu un s, ir de caractere pe post de
mesaj. Asemanător se comporta warning , care afis, ează mesajul, dar permite
continuarea execut, iei.
Uneori este de dorit să putem recupera dupa o eroare şi sa continuăm cu
un plan pentru situat, ii neprevăzute. Aceasta se poate realiza cu construct, ia
try/catch. De exemplu, secvent, a de cod de mai jos continuă să ceară o
instruct, iune validă până când d-voastră dat, i una care să se execute cu succes:
done = false;
while ~done
state = input('Enter a valid statement: ','s');
try
eval(state);
done = true;
catch me
disp('That was not a valid statement! Look:')
disp(me.message)
end
end
Într-un bloc catch se poate obt, ine cel mai recent mesaj de eroare cu
instruct, iunea lasterr, sau în versiunile mai recente MATLAB, inspectând
obiectul special de except, ie me, as, a cum s-a aratat mai sus şi cum se explică în
pagina de help pentru MException .
12
assert(~any(isinf(b)), 'Second input must be finite.')
assert(~any(isnan(b)), 'No NaNs allowed in second input.')
assert(ischar(c), 'Third input must be a string.')
Dacă prima expresie furnizată lui assert este falsă, se declanşează o eroare
cu mesajul care apare ca al doilea argument.
Deşi un header de funcţie explică numărul şi numele argumentelor de intrare
şi de ieşire, acestea nu sunt forţate la apel. În loc de aceasta, execuţia continuă
cât mai mult posibil, până se întamplă ceva nedefinit sau ilegal. Acest fapt ne
permite să acceptăm diferite numere de argumente de intrare în situaţii diferite.
O utilizare comună a listelor de argumente de lungime variabilă este să se dea
valori implicite unor valori lipsă, ca în fragmentul următor:
function shirt(neck,sleeve,color,cuff)
if nargin < 4
cuff = 'button';
if nargin < 3
color = 'blue';
end
end
13