Lekce 5 - Cykly a maticový přístup v MATLAB
Podmínky a cykly jsou základní stavební prvek rozvětveného programu. Cykly mají v MATLAB místo lehce na okraji a možná trochu překvapivou syntaxi i funkcionalitu. Koncepčně se MATLAB celkem liší od C-like jazyků a zrovna přístup k cyklům je toho hezkou ukázkou.
I přesto, že je tento článek o cyklech, obecné doporučení v MATLAB je snaha o maticové řešení. Řekneme si proč a na konci představíme pár příkladů, jak toho docílit.
Maticový přístup vs. cykly
Jak bylo zmíněno v lekcích o maticích a vektorech, MATLAB je uzpůsoben
právě na práci s nimi. Většina funkcí, kterými prostředí disponuje, je
uzpůsobeno tak, aby vstupním parametrem mohla být právě matice nebo
vícerozměrný vektor. S tím počítají i samotné operátory, takže pokud
máme vektor (v jiných jazycích mluvíme o poli) v
a chceme
všechny jeho hodnoty dělit 3
a odečíst dvojku, uděláme to
jedním řádkem:
v = [1 2 3 4 5 6 7]; v2 = v/3-2;
For cyklus
For cyklus, který dělá ekvivalentní operaci, bude vypadat následovně:
for ii = length(v) v3(ii) = v(ii) / 3 - 2; end
Takovýto zápis je zbytečné zdlouhavý a ve finále je kód neefektivní.
Nicméně vidíme, jak se for
cyklus v MATLAB konstruuje.
Syntaxe for cyklu
Cyklus začíná klíčovým slovem for
a uzavírá se
univerzálním klíčovým slovem end
(to funguje i u
if
, while
a funkcí). To zajímavé a trochu
netradiční je způsob, jakým definujeme jednotlivé průchody cyklem.
Překvapení – je to s pomocí vektoru. Tím, co je za klíčovým slovem
for
, říkáme: "vezmi vektor od jedničky do sedmičky (to je
délka vektoru v
) a každý jeho index při jednotlivých
průchodech přiřaď do proměnné ii
".
Prvky vektoru, které jsou postupně přiřazeny do ii
, vůbec
nemusíme definovat u klíčového slova for
. Pokud bychom chtěli
upravit pomocí for
cyklu pouze druhý, třetí a pátý prvek
vektoru v
, mohli bychom to udělat tímto zápisem:
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 cyklu je uvedeno i řešení bez něj. Jak již bylo řečeno na začátku, cyklům se v takovýchto případech spíše snažíme vyhnout, a proto je zde uvedeno i správnější řešení.
Ukázka definic for cyklů
Pro ukázku si zde uvedeme několik způsobů, jak napsat definici
for
cyklu. Jak již bylo zmíněno – jde především o to, jak
definovat vektor, což je podrobně popsáno v jedné z předchozích
lekcí.
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
Iterativní proměnná v cyklu je pojmenována jako dvojité ii
místo obvyklého jednoho. Důvod je obsazenost proměnné i
,
které je v MATLAB přiřazeno komplexní číslo s reálnou částí
0
a komplexní 1
. Můžete to vyzkoušet, pokud do
command window napíšete právě i
:
i ans = 0.0000 + 1.0000i
Použijete – li v cyklu i
, nic závažného se nestane,
i
se pouze předefinuje. Pokud však v takovém cyklu budete chtít
použít komplexní číslo, tak tímto způsobem nemůžete. Doporučení je
nechodit chybám naproti a raději použít jiný název proměnné.
While cyklus
Cyklus while
běží, pokud je splněna podmínka v jeho
definici. Definice se uvádí za klíčové slovo while
a celý
cyklus se uzavírá pomocí end
:
ii = 0; while (ii < 5) disp(ii); ii = ii + 1; end
Nekonečný cyklus, který se nás neustále bude dotazovat na číslo, ze kterého vypočítá desetinu, vytvoříme takto:
while(true) s = input('desetina z: '); disp(['je ' num2str(s / 10)] ); end % přerušit pomocí Ctrl + C
Další podrobnosti o tom, jak se chová podmínka ve while
cyklu, naleznete v článku o výrazech a
podmínkách. Podmínka za klíčovým slovem while
má stejná
pravidla jako za klíčovým slovem if
. Dozvíte se tam například
i to, že nikdy nekončící while
cyklus můžete rozběhnout
pomocí řetězce "nekonečno":
while('nekonecno') %vyraz bude vyhodnocen jako true input('pokracovat?','s'); end
Výraz bude vyhodnocen jako true
, jelikož řetězec
'nekonecno'
není 0
. Nutno podotknout, že proti
tomuto obskurnímu zápisu se MATLAB brání podtržením a oranžovou
hláškou.
Break a continue
Vykonávání cyklu můžeme přerušit klíčovým slovem
break
. Předchozí příklad nekonečného cyklu obohatíme o
podmínku. Jestliže vstupem, který uživatel zadá, bude písmeno
n
, cyklus se přeruší:
while(true) inp = input('pokracovat?','s'); if(inp == 'n') break; end end
continue
má podobnou funkci jako break
, nicméně
místo přerušení celého cyklu přeruší pouze aktuální iteraci a přejde
na další. Kód, který následuje za continue
, se v aktuální
iteraci neprovede:
for ii=1:25 if mod(ii, 3) == 0 % nasobek 3? continue % skoc na dalsi iteraci end disp(ii); end
Tento kód by se dal s klidem uskutečnit pomocí inverzní konstrukce
podmínky if
, či pomocí bloku else
. Avšak v
případě, že by kód za continue
(zde jeden řádek s funkcí
disp()
) byl rozsáhlejší, tak jeho umístění do jakéhokoliv
bloku snižuje přehlednost kódu.
Příklady cyklus vs. maticový přístup
Většina úloh, na které byste v jiných programovacích jazycích využili cyklus, jde v MATLAB sepsat pomocí uplatnění funkcí na vektory či matice. MATLAB je na to stavěný a maticové řešení (pokud není příliš krkolomné) je doporučené. Jednak z důvodu rychlosti, ale i přehlednosti zdrojového kódu. Pár takových příkladů si zde ukážeme.
Suma prvků
Sečtěme všechny prvky ve vektoru pomocí cyklu a pak pomocí funkce:
v = rand(100,1); % nahodny vektor o 100 prvcich suma = 0; for ii = v suma = suma +ii; end % funkce suma_m = sum(v);
Sečtení prvků dvou matic
Nyní sečtěme 2 matice, opět pomocí cyklů a poté maticově:
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;
Generovaní a vykreslení sinusovek s různou frekvencí
Následující kód vygeneruje grafy funkce sinus s různou frekvencí:

Opět si ukážeme řešení cyklem a maticí:
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)
Snížení počtu barev u šedotónové fotografie
A v posledním příkladu snížíme počet barev v černobílé fotografii:

Kód bude následující:
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ávěr
V této lekci jsme představili dva cykly, kterými MATLAB disponuje -
for
a while
. Cyklus do-while
v tomto
programovacím jazyku není a výhody cyklu foreach
přicházejí
se syntaxí cyklu for
. Dále jsme si ukázali klíčová slova
break
a continue
, jejichž fungování se neliší od
jiných jazyků.
Pro většinu operací s maticemi není vhodné cykly využívat. Přehledný kód a většinou i vyšší výkon získáme při využití maticového přístupu, na který jsou funkce MATLAB připravené. Pochopitelně jsou úlohy, kde se cykly vyloženě hodí. Doporučuji se vždy při psaní cyklu zamyslet nad tím, jestli by se úloha nedala řešit elegantněji.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 9x (2.18 kB)
Aplikace je včetně zdrojových kódů