5. diel - Cykly a maticový prístup v MATLAB
Podmienky a cykly sú základný stavebný prvok rozvetveného programu. Cykly majú v MATLAB miesto zľahka na okraji a možno trochu prekvapivou syntax i funkcionalitu. Koncepčne sa MATLAB celkom líši od C-like jazykov a zrovna prístup k cyklom zastáva peknú ukážkou.
Aj napriek tomu, že je tento článok o cykloch, všeobecné odporúčanie v MATLAB je snaha o maticové riešení. Povieme si prečo a na konci predstavíme zopár príkladov, ako to docieliť.
Maticový prístup vs. cykly
Ako bolo spomenuté v lekciách o maticiach a vektoroch, MATLAB je
prispôsobený práve na prácu s nimi. Väčšina funkcií, ktorými prostredia
disponuje, je prispôsobené tak, aby vstupným parametrom mohla byť práve
matice alebo viacrozmerný vektor. S tým počítajú aj samotné operátormi,
takže ak máme vektor (v iných jazykoch hovoríme o poli) v
a
chceme všetky jeho hodnoty deliť 3
a odpočítať dvojku,
urobíme to jedným riadkom:
v = [1 2 3 4 5 6 7]; v2 = v/3-2;
For cyklus
For cyklus, ktorý robí ekvivalentný operáciu, bude vyzerať nasledovne:
for ii = length(v) v3(ii) = v(ii) / 3 - 2; end
Takýto zápis je zbytočné zdĺhavý a vo finále je kód neefektívne.
Avšak vidíme, ako sa for
cyklus v MATLAB konštruuje.
Syntaxe for cyklu
Cyklus začína kľúčovým slovom for
a uzatvára sa
univerzálnym kľúčovým slovom end
(to funguje aj u
if
, while
a funkcií). To zaujímavé a trochu
netradičné je spôsob, akým definujeme jednotlivé priechody cyklom.
Prekvapenie - je to s pomocou vektora. Tým, čo je za kľúčovým slovom
for
, hovoríme: "vezmi vektor od jednotky do sedmičky (to je
dĺžka vektora v
) a každý jeho index pri jednotlivých
priechodoch priraď do premennej ii
".
Prvky vektora, ktoré sú postupne priradené do ii
, vôbec
nemusíme definovať u kľúčového slova for
. Ak by sme chceli
upraviť pomocou for
cyklu iba druhý, tretí a piaty prvok vektora
v
, mohli by sme to urobiť takto zápisom:
v4 = v; % nakopirovani hodnot for ii = [2, 3, 5] v4(ii) = v4(ii) / 3 - 2; end % reseni bez cyklu v4 = v; v4([2, 3, 5]) = v4([2, 3, 5]) / 3 - 2;
Po cykle je uvedené aj riešenie bez neho. Ako už bolo povedané na začiatku, cyklom sa v takýchto prípadoch skôr snažíme vyhnúť, a preto je tu uvedené i správnejšie riešenie.
Ukážka definícií for cyklov
Pre ukážku si tu uvedieme niekoľko spôsobov, ako napísať definícii
for
cyklu. Ako už bolo spomenuté - ide predovšetkým o to, ako
definovať vektor, čo je podrobne popísané v jednej z predchádzajúcich
lekcií.
for ii = 9:-1:-9 end % od 9 sestupne k -9 for ii = linspace(2,23,101) end %interval od 2 do 23 ve 101 prvcich for ii = 0:1e-3:1 end % od 0 do 1 po 1 tisicine for ii = randi(100,30) end %30 nahodnych cisel od 1 do 100
Dvojité ii vs. i
Iteratívny premenná v cykle je pomenovaná ako dvojité ii
namiesto obvyklého jedného. Dôvod je obsadenosť premenné i
,
ktoré je v MATLAB priradené komplexné číslo s reálnou časťou
0
a komplexné 1
. Môžete to vyskúšať, ak do
command window napíšete práve i
:
i ans = 0.0000 + 1.0000i
Použijete - ak v cykle i
, nič závažné sa nestane,
i
sa iba predefinuje. Ak však v takomto cykle budete chcieť
použiť komplexné číslo, tak týmto spôsobom nemôžete. Odporúčanie je
nechodiť chybám naproti a radšej použiť iný názov premennej.
While cyklus
Cyklus while
beží, keď je splnená podmienka v jeho
definícii. Definícia sa uvádza za kľúčové slovo while
a
celý cyklus sa uzatvára pomocou end
:
ii = 0; while (ii < 5) disp(ii); ii = ii + 1; end
Nekonečný cyklus, ktorý sa nás neustále bude pýtať na číslo, z ktorého vypočíta desatinu, vytvoríme takto:
while(true) s = input('desetina z: '); disp(['je ' num2str(s / 10)] ); end % přerušit pomocí Ctrl + C
Ďalšie podrobnosti o tom, ako sa správa podmienka vo while
cyklu, nájdete v článku o výrazoch a
podmienkach. Podmienka za kľúčovým slovom while
má
rovnaké pravidlá ako za kľúčovým slovom if
. Dozviete sa tam
napríklad aj to, že nikdy nekončiaci while
cyklus môžete
rozbehnúť pomocou reťazca "nekonečno":
while('nekonecno') %vyraz bude vyhodnocen jako true input('pokracovat?','s'); end
Výraz bude vyhodnotený ako true
, pretože reťazec
'nekonecno'
nie je 0
. Treba podotknúť, že proti
tomuto obskurnímu zápisu sa MATLAB bráni podčiarknutím a oranžovú
hláškou.
Break a continue
Vykonávanie cyklu môžeme prerušiť kľúčovým slovom
break
. Predchádzajúci príklad nekonečného cyklu obohatíme o
podmienku. Ak vstupom, ktorý užívateľ zadá, bude písmeno n
,
cyklus sa preruší:
while(true) inp = input('pokracovat?','s'); if(inp == 'n') break; end end
continue
má podobnú funkciu ako break
, však
miesto prerušenie celého cyklu preruší iba aktuálny iterácii a prejde na
ďalšie. Kód, ktorý nasleduje za continue
, sa v aktuálnej
iterácii nevykoná:
for ii=1:25 if mod(ii, 3) == 0 % nasobek 3? continue % skoc na dalsi iteraci end disp(ii); end
Tento kód by sa dal s kľudom uskutočniť pomocou inverzné konštrukcie
podmienky if
, či pomocou bloku else
. Avšak v
prípade, že by kód za continue
(tu jeden riadok s funkciou
disp()
) bol rozsiahlejší, tak jeho umiestnenie do akéhokoľvek
bloku znižuje prehľadnosť kódu.
Príklady cyklus vs. maticový prístup
Väčšina úloh, na ktoré by ste v iných programovacích jazykoch využili cyklus, ide v MATLAB spísať pomocou uplatnenie funkcií na vektory či matice. MATLAB je na to stavaný a maticové riešenie (ak nie je príliš krkolomné) je odporúčané. Jednak z dôvodu rýchlosti, ale aj prehľadnosti zdrojového kódu. Pár takých príkladov si tu ukážeme.
Suma prvkov
Sčítame všetky prvky vo vektora pomocou cyklu a potom pomocou funkcie:
v = rand(100,1); % nahodny vektor o 100 prvcich suma = 0; for ii = v suma = suma +ii; end % funkce suma_m = sum(v);
Sčítaní prvkov dvoch matíc
Teraz sčítame 2 matice, opäť pomocou cyklov a potom maticovo:
A = rand(100); %nahodna matice 100x100 B = rand(100); C = zeros(size(A)); for ii = 1:size(A,1) for yy = 1:size(A,2) C(ii,yy) = A(ii,yy) +B(ii,yy); end end % maticove C_m = A+B;
Generovanie a vykreslenie sinusovek s rôznou frekvenciou
Nasledujúci kód vygeneruje grafy funkcie sínus s rôznou frekvenciou:
Opäť si ukážeme riešenie cyklom a maticou:
t = 0:0.01:1; % vektor casu f = [1; 2; 3]; % frekvence 1 2 a 3 Hz % reseni cyklem figure;subplot 211; hold on; for ii = f v = sin(2 * pi * ii * t); plot(t, v, 'LineWidth', 3) end % reseni matici subplot 212; A = sin(2 * pi * f * t); plot(t, A', 'LineWidth', 3)
Zníženie počtu farieb u šedotónové fotografie
A v poslednom príklade znížime počet farieb v čiernobielej fotografii:
Kód bude nasledujúci:
Fotka = imread('cameraman.tif'); Fotka2 = Fotka; for ii = 1:size(Fotka, 1) for yy = 1:size(Fotka, 2) Fotka2(ii, yy) = uint8(round(Fotka2(ii, yy) / 255 * 3) * 128); end end subplot 121; imshow(Fotka); subplot 122; imshow(Fotka2) % maticove M = uint8(round((Fotka / 255) * 3) * 128); % pouze 3 barvy (0, 128, 255) figure; imshow(M)
Záver
V tejto lekcii sme predstavili dva cykly, ktorými MATLAB disponuje -
for
a while
. Cyklus do-while
v tomto
programovacom jazyku nie je a výhody cyklu foreach
prichádzajú
so syntaxou cyklu for
. Ďalej sme si ukázali kľúčové slová
break
a continue
, ktorých fungovanie sa nelíši od
iných jazykov.
Pre väčšinu operácií s maticami nie je vhodné cykly využívať. Prehľadný kód a väčšinou aj vyšší výkon získame pri využití maticového prístupu, na ktorý sú funkcie MATLAB pripravené. Pochopiteľne sú úlohy, kde sa cykly vyložene hodí. Odporúčam sa vždy pri písaní cykle zamyslieť nad tým, či by sa úloha nedala riešiť elegantnejšie.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 9x (2.18 kB)
Aplikácia je vrátane zdrojových kódov