|
4. Větvení a rozhodování |
|
|
|
- Motto: Jestliže je v jedné funkci příliš mnoho příkazů
IF, pak se její autor patrně minul povoláním. Už jste někdy
viděli letecký snímek velkého nádraží? V České Třebové je
celá řada výhybek, se kterými se nehýbe a kolejí, po kterých
se nikdy nejezdilo.
- Bez větvení – každý příkaz se provede právě jednou
(v uvedeném pořadí)
S větvením – každý příkaz uvnitř
větvení se provede nejvýše jednou
- Větvení má svůj začátek – if logická_podmínka
Větvení má svůj konec – end
Větvení má své tělo – libovolné příkazy mezi if a end
Uvnitř větvení může být použito klíčové slovo else
Pozitivní část těla – příkazy mezi if a else, chybí-li else,
je celé tělo pozitivní
Negativní část těla – příkaz mezi else a end, chybí-li else,
chybí i negativní část
Příkaz return – v těle větvení můžeme realizovat předčasný únik
z funkce
- Syntaxe úplné podmínky:
|
|
|
if podminka
% prikazy pozitivni casti
else
% prikazy negativni casti
end
|
|
|
- Syntaxe neúplné podmínky:
|
|
|
if podminka
% prikazy pozitivni casti
end
|
|
|
- Příklad kompletního větvení:
|
|
|
if IQ>=95
zamysli_se;
else
najez_se;
end
jdi_domu;
|
|
|
- Příklad větvení bez negativní části:
|
|
|
if cas==6
vstavej;
snidej;
vypadni;
end
jdi_do_prace;
|
|
|
- Větvení může být nejen za jiným větvením, ale i uvnitř těla jiného větvení
|
|
|
Příklad 4A.1: |
|
|
Přeložte z angličtiny: If I am thirsty I will go to the pub. If I am happy
I will drink milk. Anyway I will drink wine. Then I will pay and go home.
Předpoklad: V proměnných thirsty a happy jsou logické hodnoty 0 nebo 1.
Ostatní názvy jsou názvy funkcí bez vstupních a výstupních parametrů.
|
|
|
Řešení: |
|
|
Příklad použití větvení |
|
|
if thirsty |
go_to_the_pub; |
if happy |
drink_milk; |
else |
drink_wine; |
end |
end |
|
|
|
|
- Heslo dne: Kdo nekrokuje větvení, nedozví se, kudy mu ujel vlak.
Poznámka 1: Větvení umožňuje elegantně odvracet nebezpečí vzniku chyb.
Poznámka 2: Větvení umožňuje realizovat úplnou diskusi řešení problému.
Poznámka 3: Elegance spočívá v úplném rozboru s minimálním počtem if příkazů.
|
|
|
Příklad 4A.2: |
|
|
Sestavte funkci na výpočet podílu sinu x a uvedeného x.
Instrukce: chování v okolí nuly je také důležité, Taylorova řada,
dodefinování funkce v okolí nuly, krokování.
|
|
|
Řešení: |
|
|
function [y]=SinX(x) |
% Funkce sin(x)/x dodefinovana v bode x=0 na spojitou funkci |
% [y]=SinX(x); |
% y ... hodnota funkce |
% x ... hodnota nezavisle promenne |
if abs(x)<=1e-6 |
% test blizkosti k nule |
y=1-x^2/6; |
% Tayloruv rozvoj pro x=0 |
else |
y=sin(x)/x; |
% normalni a primocary vypocet |
end |
|
|
|
|
Příklad 4A.3: |
|
|
Sestavte funkci na výpočet minima ze tří hodnot.
Instrukce: dvě větvení uvnitř obou částí hlavního větvení,
rozbor, co když nastane rovnost hodnot, krokování.
|
|
|
Řešení: |
|
|
function [m]=Min3(x,y,z) |
% Vypocet minima ze tri hodnot stejneho typu |
% [m]=Min3(x,y,z); |
% m ... minimalni hodnota |
% x,y,z ... vstupni hodnoty |
if x<y |
% zakladni otazka |
if x<z |
% mozna to je x |
m=x; |
% urcite to je x |
else |
m=z; |
% urcite to je z |
end |
else |
if y<z |
% mozna to je y |
m=y; |
% urcite to je y |
else |
m=z; |
% urcite to je z |
end |
end |
|
|
|
|
Příklad 4A.4: |
|
|
Sestavte funkci na výpočet polohy minima/minim ze tří hodnot.
Instrukce: volání funkce Min3, postupné naplňování vektoru poloh minim, krokování.
|
|
|
Řešení: |
|
|
function [arg,mini]=ArgMin3(x,y,z) |
% Vypocet polohy minim(a) ze tri hodnot stejneho typu |
% [arg,mini]=ArgMin3(x,y,z); |
% arg .... vektor polohy minim(a) |
% mini ... minimalni hodnota |
% x,y,z .. vstupni hodnoty |
arg=[]; |
% jeste jsme nic nenasli |
mini=Min3(x,y,z); |
% hodnota minima (minim) |
if x==mini |
% mozna to je x |
arg=[arg 1]; |
% pridat do vektoru arg |
end |
if y==mini |
% mozna to je y |
arg=[arg 2]; |
% pridat do vektoru arg |
end |
if z==mini |
% mozna to je z |
arg=[arg 3]; |
% pridat do vektoru arg |
end |
|
|
|
|
Příklad 4A.5: |
|
|
Jsou situace, kde systém Matlab pomáhá problém řešit bez větvení
s využitím vektorizace a vestavěných funkcí. Tyto funkce mají ale
větvení uvnitř, takže se stejně někde větví, akorát my to nemusíme
vytvářet. Copak asi dělá funkce:
|
|
|
function [m]=CENZUROVANO(x,y,z) |
% CENZUROVANO |
% [m]=CENZUROVANO(x,y,z); |
% m, x, y, z ...CENZUROVANO |
m=min([x y z]); |
% to je konec |
|
|
|
|
Příklad 4A.6: |
|
|
Sestavte funkci na výpočet počtu jízd výtahem. Výtah má omezenou nosnost
a jsou známy hmotnosti tří obchodních cestujících, kteří jedou
ze suterénu do 11 patra.
Instrukce: přemýšlejte, vytvořte lepší řešení, krokujte.
|
|
|
Řešení: |
|
|
function [n]=Vytah3(a,b,c,w) |
% Vytah a tri pasazeri |
% [n]=Vytah3(a,b,c,w); |
% n ... pocet jizd vytahem |
% a,b,c ... hmotnosti jednotlivych pasazeru |
% w ... maximalni nosnost vytahu |
if a+b+c<=w |
% mozna se vejdou vsichni najednou |
n=1; |
% staci jedna jizda |
return; |
% koncime a pryc od toho |
end |
if a>w | b>w | c>w |
% mozna je mezi nimi Cerny Petr |
n=inf; |
% nikdy se tam vsichni nedostanou |
return; |
% koncime a pryc od toho |
end |
% mozna by se nasla alespon dvojice |
if a+b<=w | b+c<=w | a+c<=w |
n=2; |
% nutne jsou dve jizdy |
return; |
% koncime a pryc od toho |
end |
n=3 |
% je definitivne prokazano, ze kazdy musi jet extra |
|
|
|
|
- S použitím matlabovské funkce sort lze vytvořit elegantnější verzi výtahu.
|
|
|
function [n]=JinyVytah3(a,b,c,w) |
% Vytah a tri pasazeri s pouzitim trideni |
% [n]=JinyVytah3(a,b,c,w); |
% n ... pocet jizd vytahem |
% a,b,c ... hmotnosti jednotlivych pasazeru |
% w ... maximalni nosnost vytahu |
h=sort([a b c]); |
% setridime je podle vzrustajici hmotnosti |
if h(1)+h(2)+h(3)<=w |
% mozna se vejdou vsichni najednou |
n=1; |
% staci jedna jizda |
return; |
% koncime a pryc od toho |
end |
if h(3)>w |
% mozna je mezi nimi Cerny Petr |
n=inf; |
% nikdy se tam vsichni nedostanou |
return; |
% koncime a pryc od toho |
end |
if h(1)+h(2)<=w |
% mozna by se vesla alespon nejlehci dvojice |
n=2; |
% nutne jsou dve jizdy |
return; |
% koncime a pryc od toho |
end |
n=3 |
% je definitivne prokazano, ze kazdy musi jet extra |
|
|
|
|
Příklad 4A.7: |
|
|
Sestavte funkci na výpočet řešení linearní rovnice.
Instrukce: Každý problém lze řešit ledabyle. Při programování
dejme přednost důslednosti. Funkci řádně otestujte. Funguje
i pro nulové a komplexní hodnoty parametrů?
|
|
|
Řešení: |
|
|
function [x]=Linearni(a,b) |
% Reseni linearni rovnice a*x+b=0 |
% [x]=Linearni(a,b); |
% x ... vektor reseni |
% a ... linearni clen |
% b ... absolutni clen |
if a==0 |
% mozna, ze je degenerovana |
if b~=0 |
% mozna, ze nema reseni |
x=[] |
% nema reseni |
else |
x=inf; |
% ma nekonecne mnoho reseni |
end |
else |
x=-b/a; |
% ma prave jedno reseni |
end |
|
|
|
|
Příklad 4A.8: |
|
|
Sestavte funkci pro nalezení všech řešení redukované kvadratické rovnice.
Instrukce: Úlohu vyřešme nejprve naivně pouze s použitím středoškolských
vzorců a s úplnou diskusí. Jistě oceníte, že funkce automaticky
pracuje i s komplexní proměnnou.
|
|
|
Řešení: |
|
|
function [x]=KvadratRedNaive(p,q) |
%
Naivni reseni redukovane kvadraticke rovnice x^2+p*x+q=0 |
% [x]=KvadratRedNaive(p,q); |
% x ... vektor vsech reseni |
% p ... linearni clen |
% q ... absolutni clen |
r=p/2; |
% z rozmaru? |
d=r^2-q; |
% vypocet diskriminantu |
if d==0 |
% mozna, ze ma jen jedno reseni |
x=-r; |
% ma dvojnasobny koren |
else |
% 2 ruzne realne nebo komplexni koreny |
x=[-r+sqrt(d) -r-sqrt(d)]; |
end |
|
|
|
- Při numerických výpočtech velmi vadí, když rozdíl dvou
velkých čísel je v absolutní hodnotě malý, neboť zaokrouhlovací chyby
se okamžitě chopí své životní šance. Ten, kdo umí rozšiřovat zlomek
s odmocninami, jistě ví, co s tím udělat a proč. Vy ostatní
alespoň nalezněte takové p, q, aby vynikl rozdíl mezi KvadratRedNaive
a exaktním řešením. Pak oceníte následující funkci:
|
|
|
function [x]=KvadratRed(p,q) |
%
Robustni reseni redukovane kvadraticke rovnice x^2+p*x+q=0 |
% [x]=KvadratRed(p,q); |
% x ... vektor vsech reseni |
% p ... linearni clen |
% q ... absolutni clen |
r=p/2; |
% z rozmaru? |
d=r^2-q; |
% vypocet diskriminantu |
if d==0 |
% mozna, ze ma jen jedno reseni |
x=-r; |
% ma dvojnasobny koren |
else |
v=sqrt(d); |
% pomocny vypocet |
u=-r+v; |
% -r+sqrt(d) |
v=-r-v; |
% -r-sqrt(d) |
if abs(u)>abs(v) |
% kdo je vetsi ? |
x=[u +q/u]; |
% odvodte si rozsirovanim zlomku |
else |
x=[q/v v]; |
% jeste jednou promyslete |
end |
end |
|
|
|
Příklad 4A.9: |
|
|
Úloha: Sestavte funkci na úplnou diskusi řešení kvadratické rovnice.
Instrukce: volání funkce Linearni a KvadratRed, otestujte, krokujte.
|
|
|
Řešení: |
|
|
function [x]=Kvadraticka(a,b,c) |
% Vsechna reseni kvadraticke rovnice a*x^2+b*x+c=0 |
% [x]=Kvadraticka(a,b,c); |
% x ... vektor vsech reseni |
% a ... kvadraticky clen |
% b ... linearni clen |
% c ... absolutni clen |
if a==0 |
% mozna, ze je to jenom linearni rovnice |
x=Linearni(b,c); |
% resi to snadno nekdo jiny |
else |
x=KvadratRed(b/a,c/a); |
% vydelenim ziskame redukovany tvar |
end |
|
|
|
Příklady pro samostatné vypracování |
|
|
Příklad 4B.1: |
|
|
Vylepšete funkci Remen tak, aby kola byla reálných rozměrů.
|
|
|
|
Příklad 4B.2: |
|
|
Vylepšete funkci Uhel tak, aby počet minut a sekund byl omezen.
|
|
|
|
Příklad 4B.3: |
|
|
Sestavte funkci pro posouzení sestrojitelnosti trojúhelníka.
|
|
|
|
Příklad 4B.4: |
|
|
Vylepšete funkci na výpočet plochy trojúhelníka pomocí Heronova vzorce.
|
|
|
|
Příklad 4B.5: |
|
|
Vylepšete funkci na určení hloubky vodního toku.
|
|
|
|
Příklad 4B.6: |
|
|
Sestavte funkci na nalezení maxima ze tří hodnot včetně polohy.
|
|
|
|
Příklad 4B.7: |
|
|
Sestavte funkci pro úplnou diskusi řešení rovnice třetího stupně.
|
|
|
|
Příklad 4B.8: |
|
|
Sestavte funkci pro zjištění celkového odporu sériové a paralelní kombinace tří odporů.
|
|
|
|
Příklad 4B.9: |
|
|
Sestavte funkci pro výpočet doby společné práce pro maximálně
pět osob, které celou dobu pracují společně na jedné věci a nepřekážejí si.
|
|
|
|
Příklad 4B.10: |
|
|
Sestavte funkci na nalezení mediánu ze tří hodnot včetně polohy.
|
|
|
|
Příklad 4B.11: |
|
|
Sestavte funkci na nalezení geometrického průměru z maximálně pěti hodnot.
|
|
|
|
Příklad 4B.12: |
|
|
Sestavte funkci pro nalezení harmonického průměru z maximálně pěti hodnot.
|
|
|
|
Seznam použitých příkazů |
|
|
if, return, sort
|
|
|