Table of Contents

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
test = true;
if test
disp('Podminka byla splnena.');
end
Podminka byla splnena.
% Priklad if/else
if test
disp('Podminka byla splnena.');
else
disp('Podminka nebyla splnena.');
end
Podminka byla splnena.
% Priklad if/elseif/else
test1 = false;
test2 = true;
if test1
disp('Podminka 1 byla splnena.');
elseif test2
disp('Podminka 1 nebyla splnena.');
disp('Podminka 2 byla splnena.');
else
disp('Nebyla splnena zadna z podminek.');
end
Podminka 1 nebyla splnena.
Podminka 2 byla 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

Logické operátory

Dále lze využít další funkce (např. all, any), které vrací hodnoty true/false nebo jimi tvořené vektory.
% Priklad if
testValue1 = 1e-5;
testValue2 = 1;
A = 0.05;
if ( A > testValue1 ) && ( A < testValue2 )
disp(['A je vetsi nez ', num2str(testValue1), ...
' a mensi nez ',num2str(testValue2)]);
else
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ý.
vek = 15;
switch vek
case 14
disp('Promenna vek je rovna 14.')
case 15
disp('Promenna vek je rovna 15.')
otherwise
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í.
% Vypsani cisel 1 az 100
for n = 1:10
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
disp( A( idx, : ) );
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
x = linspace(0,2*pi,25);
y = sin(x);
bool_run = false;
if bool_run
figure
xlabel('x'); ylabel('y');
grid on; hold on;
xlim([0 2*pi]); ylim([-1 1]);
for in = 1:length(y)
plot(x(in),y(in),'x');
drawnow;
pause(0.2);
end
hold off
end

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.
value = 5;
while value > 0.1
value = value/2;
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:
a = 4;
x1 = a; diference = 10; % nulta iterace
while abs(diference) > 1e-10
x2 = 1/2*(x1 + a/x1); % update x2
diference = x2 - x1; % update dif
x1 = x2; % update x1
disp(x2); % zobrazeni
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
data = [1 2 3 NaN 5 6];
for in = 1:length(data)
if isnan(data(in))
disp(['NaN hodnota na pozici ', num2str(in)]);
break;
end
end
NaN hodnota na pozici 4

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)
if vzdalenosti(in) > 15
disp(['Bod ' num2str(in) ' je moc daleko'])
continue;
end
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):
  1. Pro každé N přičtěte náhodnou hodnotu s rovnoměrným rozdělením od 1 do 20 (randi).
  2. 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).
  3. Podle výsledku ze 2 vypište:
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:
  1. Před prvním dělením jsou k dispozici dvě buňky.
  2. 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í.
  3. 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í:
  1. Určete součet všech buněk na konci N-tého dne dělení (sum).
  2. Určete procentuální počet buněk, které se každý den dělily.
  3. 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í:
  1. Definujte proměnnou TEST rovnou např. 1. Dále definujte proměnnou Y rovnu vstupní hodnotě X.
  2. Využijte while cyklus, který bude probíhat tak dlouho, dokud TEST nesplní podmínku přesnosti (TEST > 1e−15).
  3. Ve while cyklu definujte proměnnou Y0 rovnu hodnotě Y.
  4. Dále přepočítejte hodnotu proměnné Y dle rekurzivního vztahu.
  5. 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.