Základy programování v Matlabu - část 3
Ing. Petr Pokorný, Ph.D.
Řízení toku programu
Podmínky - příkaz if
Testuje jednu nebo více podmínek na pravdu (true/false).
% Priklad jednoduche podminky
disp('Podminka byla splnena.');
disp('Podminka byla splnena.');
disp('Podminka nebyla splnena.');
disp('Podminka 1 byla splnena.');
disp('Podminka 1 nebyla splnena.');
disp('Podminka 2 byla splnena.');
disp('Nebyla splnena zadna z podminek.');
end
Podminka 1 nebyla splnena.
Podmínka bude splněna, kdykoli je příkaz za klíčovým if splněn. K formulaci testovacích příkazů používáme relační a logické operátory.
Relační operátory
- == je rovno
- ~= není rovno
- < je menší
- <= je menší nebo rovno
- > je větší
- >= je větší nebo rovno
Logické operátory
- & AND, stejná priorita jako OR
- | OR, stejná priorita jako AND
- ~ NOT - nejvyšší priorita
Dále lze využít další funkce (např. all, any), které vrací hodnoty true/false nebo jimi tvořené vektory.
if ( A > testValue1 ) && ( A < testValue2 )
disp(['A je vetsi nez ', num2str(testValue1), ...
' a mensi nez ',num2str(testValue2)]);
disp('A je mimo kriticky rozsah.');
end
A je vetsi nez 1e-05 a mensi nez 1
Poznámka: Využili jsme funkci num2str, která převádí numerickou hodnotu na textový řetězec.
Podmínky - příkaz switch
Větvení programu na takové případy, kdy se dotazovaná proměnná může rovnat různým hodnotám.
Počet případů (case) není omezen.
Příkaz otherwise není povinný.
disp('Promenna vek je rovna 14.')
disp('Promenna vek je rovna 15.')
disp('Promenna vek neni 14 ani 15.')
end
Promenna vek je rovna 15.
Cykly - příkaz for
Cykly využíváme, má-li se opakovat určitá část kódu (iterace, procházení prvků matice, načítání textu řádek po řádku, ...).
Za klíčovým slovem for následuje proměnná, jejíž hodnota se v průběhu cyklu (opakování) mění (např. konstantně narůstá, ...). Hodnoty této proměnné definujeme vektorem. Délka tohoto vektoru určuje počet opakování.
disp( [ 'Cislo ' num2str(n) ] );
end
Cislo 1
Cislo 2
Cislo 3
Cislo 4
Cislo 5
Cislo 6
Cislo 7
Cislo 8
Cislo 9
Cislo 10
% Vypis lichych radku matice
A = rand(100,5); % vytvoreni matice
for idx = 1:2:size(A,1) % n je vektor 1, 3, ... az pocet radku matice
end
0.8147 0.1622 0.6443 0.0596 0.4229
0.1270 0.3112 0.8116 0.0424 0.5985
0.6324 0.1656 0.3507 0.5216 0.6959
0.2785 0.2630 0.8759 0.8181 0.6385
0.9575 0.6892 0.6225 0.7224 0.0688
0.1576 0.4505 0.2077 0.6596 0.5309
0.9572 0.2290 0.4709 0.9730 0.4076
0.8003 0.1524 0.8443 0.8003 0.7184
0.4218 0.5383 0.2259 0.4324 0.5313
0.7922 0.0782 0.2277 0.0835 0.1056
0.6557 0.1067 0.3111 0.1734 0.7788
0.8491 0.0046 0.4302 0.8314 0.0908
0.6787 0.8173 0.9049 0.0605 0.1537
0.7431 0.0844 0.4389 0.5269 0.4401
0.6555 0.2599 0.2581 0.6569 0.4574
0.7060 0.4314 0.5949 0.2920 0.5181
0.2769 0.1818 0.6028 0.0155 0.6377
0.0971 0.1455 0.2217 0.1672 0.2407
0.6948 0.8693 0.2967 0.3724 0.2891
0.9502 0.5499 0.4242 0.4897 0.6951
0.4387 0.8530 0.0855 0.9516 0.2548
0.7655 0.3510 0.8010 0.0527 0.6678
0.1869 0.4018 0.9289 0.2691 0.3445
0.4456 0.2399 0.4886 0.5479 0.6753
0.7094 0.1839 0.2373 0.4177 0.6022
0.2760 0.4173 0.9631 0.3015 0.9160
0.6551 0.9027 0.5211 0.6663 0.4624
0.1190 0.4909 0.4889 0.6981 0.4609
0.9597 0.3377 0.6791 0.1781 0.3225
0.5853 0.3692 0.3674 0.9991 0.4714
0.7513 0.7803 0.0377 0.0326 0.1759
0.5060 0.2417 0.9133 0.8819 0.4735
0.8909 0.0965 0.0987 0.1904 0.3411
0.5472 0.9421 0.3354 0.4607 0.1917
0.1493 0.5752 0.1366 0.1564 0.2428
0.8407 0.2348 0.1068 0.6448 0.2691
0.8143 0.8212 0.4942 0.1909 0.1887
0.9293 0.0430 0.7150 0.4820 0.0911
0.1966 0.6491 0.8909 0.5895 0.6834
0.6160 0.6477 0.6987 0.3846 0.4257
0.3517 0.5470 0.0305 0.2518 0.6476
0.5853 0.7447 0.5000 0.6171 0.6358
0.9172 0.6868 0.9047 0.8244 0.2089
0.7572 0.3685 0.6177 0.7302 0.2362
0.3804 0.7802 0.8055 0.5841 0.6073
0.0759 0.9294 0.1829 0.9063 0.4587
0.5308 0.4868 0.8865 0.8178 0.7703
0.9340 0.4468 0.4899 0.5944 0.6620
0.5688 0.5085 0.9787 0.4253 0.8419
0.0119 0.8176 0.5005 0.1615 0.2564
Poznámka: Tento příklad lze řešit elegantně tzv. vektorizací (viz dále).
% Priklad jednoduche animace
xlabel('x'); ylabel('y');
xlim([0 2*pi]); ylim([-1 1]);
Cykly - příkaz while
While cyklus probíhá do té doby, dokud je splněna vstupní podmínka. Nemusíme znát počet opakování cyklu.
disp(['hodnota je: ',num2str(value)])
end
hodnota je: 2.5
hodnota je: 1.25
hodnota je: 0.625
hodnota je: 0.3125
hodnota je: 0.15625
hodnota je: 0.078125
Newtonova metoda pro hledání druhé odmocniny:
x1 = a; diference = 10; % nulta iterace
while abs(diference) > 1e-10
x2 = 1/2*(x1 + a/x1); % update x2
diference = x2 - x1; % update dif
end
2.5000
2.0500
2.0006
2.0000
2.0000
2
Vynucené zastavení cyklu - příkaz break
break - vynucené zastavení for nebo while cyklu
disp(['NaN hodnota na pozici ', num2str(in)]);
Vynucené pokračování v další iteraci - příkaz continue
continue - okamžité spuštění dalšího kroku cyklu s vynecháním zbytku aktuálního
vzdalenosti = [10 21 32 12 25 16];
for in = 1:length(vzdalenosti)
disp(['Bod ' num2str(in) ' je moc daleko'])
disp(['Bod ' num2str(in) ' je ve vzdalenosti ' num2str(vzdalenosti(in)) ' m'])
end
Bod 1 je ve vzdalenosti 10 m
Bod 2 je moc daleko
Bod 3 je moc daleko
Bod 4 je ve vzdalenosti 12 m
Bod 5 je moc daleko
Bod 6 je moc daleko
Příklady
Příklad 1
Vytvořte soubor podminky1.m a vyčistěte prostředí (clc, close all, clear all). Pro N od 1 do 10 vytvořte následující for-cyklus (for):
- Pro každé N přičtěte náhodnou hodnotu s rovnoměrným rozdělením od 1 do 20 (randi).
- V každém kroku rozhodněte, zda-li tato nová hodnota dělitelná 2, 3, oběma nebo ani jednou z nich (mod, rem).
- Podle výsledku ze 2 vypište:
- Je-li hodnota dělitelná 2, vypište: „Hondnota X je dělitelná 2,“ kde X je nová hodnota (if, disp, num2str).
- Je-li hodnota dělitelná 3, vypište: „Hondnota X je dělitelná 3,“ kde X je nová hodnota.
- Je-li hodnota dělitelná 2 i 3, vypište: „Hondnota X je dělitelná 2 i 3,“ kde X je nová hodnota.
Není-li hodnota dělitelná 2 ani 3, vypište: „Hondnota X není dělitelná 2 ani 3,“ kde X je nová hodnota.
Příklad 2
Napište jednoduchý program podminky2.m, který bude simulovat dělení buňek po dobu N dnů a který bude vypisovat základní statistické údaje viz následující podmínky:
- Před prvním dělením jsou k dispozici dvě buňky.
- Každá buňka se dělí maximálně jednou denně na dvě. Každá buňka se v jednom dni může dělit, ale nemusí.
- Rozhodnutí, zda-li se bude buňka dělit, se řídí rovnoměrným rozdělením pravděpodobnosti (1 ano, 0 ne, randi).
Určete následující:
- Určete součet všech buněk na konci N-tého dne dělení (sum).
- Určete procentuální počet buněk, které se každý den dělily.
- Zobrazte graf závislosti celkového počtu buněk na dnech (plot). Porovnejte s exponenciálním růstem, který by odpovídal tomu, že se každá buňka bude každý den dělit („počet na konci dne“ = 2N).
V programu libovolně využijte funkce řízení toku for a podmínky if, else, elseif.
Příklad 3
Vytvořte soubor odmocnina.m a vyčistěte prostředí (clc, close all, clear all).
Napište kód, který bude iterativně počítat odmocninu z reálného čísla x s přesností 1e−15. Využijte rekurentní vztah pro
daný jako: K výpočtu využijte funkci while.
Možné řešení:
- Definujte proměnnou TEST rovnou např. 1. Dále definujte proměnnou Y rovnu vstupní hodnotě X.
- Využijte while cyklus, který bude probíhat tak dlouho, dokud TEST nesplní podmínku přesnosti (TEST > 1e−15).
- Ve while cyklu definujte proměnnou Y0 rovnu hodnotě Y.
- Dále přepočítejte hodnotu proměnné Y dle rekurzivního vztahu.
- Hodnotu TEST přepočítejte jako absolutní hodnotu rozdílu hodnot Y a Y0.
Určete také počet iterací, který byl třeba k výpočtu hodnoty y. Porovnejte získané výsledky s hodnotou funkce sqrt.
Příklad 4
Vytvořte soubor vyhlazeni.m a vyčistěte prostředí (clc, close all, clear all).
Vytvořte vektor X = [1, 1.4, 2, 2.9, 3.5, 4, 5.1, 7, 8.2, 9.1, 9.3, 9.5, 10]. Dále vytvořte vektor Y s hodnotami √(X) + "náhodně generované číslo" s normálním rozdělením s nulovou střední hodnotou a směrodatnou odchylkou 0.1.
Vytvořte algoritmus pro vyhlazení dat, který průměruje data v okolí ±W/2 okolo daného bodu X, kde W je libovolná šířka průměrujícího intervalu (reálné číslo). Filtrovaná data zobrazte do vhodného grafu.