V této lekci se nejprve zaměříme na řešení soustav rovnic a následně si představíme podmíněný příkaz IF.
Řešení soustav rovnic s využitím GNU/Octave¶
Soustavy rovnic se v GNU/Octave řeší maticově, proto si nejprve ukážeme základy práce s vektory a matičemi v Octave
Již jsme si ukázali, že pokud chceme do proměnné uložit hodnotu, použíjeme symbol .
a=7a = 7
Pokud chceme vytvořit řádkový vektor, použijeme hranáté závorky a jednotlivé prvky vektoru oddělíme mezerou.
vektor=[3 4 7]vektor =
3 4 7
Místo mezer můžeme pro oddělení prvků použít i čárku.
vektor=[3, 4, 7]vektor =
3 4 7
Čárky a mezery lze kombinovat.
vektor=[3 4, 7]vektor =
3 4 7
Pokud chceme zjistit rozměry vektoru (který máme uložený v nějaké proměnné), můžeme použít příkaz size().
size(vektor)ans =
1 3
Vidíme, že náš vektor má jeden řádek a tři sloupce. Může se zdát nesmyslné, že dostáváme dvě hodnoty místo jedné, ale takto jsme schopni zjistit zda je vektor sloupcový nebo řádkový. Navíc příkaz size() lze použít i na matice.
Pokud bychom chtěli vytvořit sloupcový vektor, musíme pro oddělení použít středník.
vektor_sloupcovy=[3; 4; 7]vektor_sloupcovy =
3
4
7
Pro trasformaci vektoru ze sloupcového na řádkový (a naopak) se používá symbol '.
% transformuj vektor "vektor_sloupcovy" a vysledek uloz do vektoru "vektor radkovy"
vektor_radkovy=vektor_sloupcovy'vektor_radkovy =
3 4 7
Vektor lze samozřejmě vytvářet z již existujících vektoru:
%Do promennych x_1 a x_2 uloz hodnoty 1 a 2.
x_1=2
x_2=3
%vytvor radkovy vektor x, ktery bude mit na prvni pozici promennou x_1 a na druhe x_2
x=[x_1, x_2]x_1 = 2
x_2 = 3
vektorvektor =
3 4 7
Hodnoty uložené ve vektoru lze dle potřeby měnit
%ctyrka se nam nelibi, ma tam byt 1
vektor=[1 2 3]
%pokud chceme mit na druhe pozici 1, pouzijeme nasledujici prikaz
vektor(2)=1vektor =
1 2 3
vektor =
1 1 3
Při změně hodnoty se nemusíme odkazovat jen jednou souřadnicí (prvek vektoru), ale můžeme použít řádek a sloupec (toto je užitečné u matic).
vektor(1,2)=2vektor =
1 2 3
Matice vytváříme obdobně jako vektor, jen musíme kombinovat oddělovač prvků na řádku (mezera, čárka) a oddělovač řádků (středník).
A=[1 2;3 4]A =
1 2
3 4
Pokud bychom chtěli řešit následujicí soustavu rovnic:
využijeme toho, že lze soustavu zapsat maticově:
kde
, a .
Matici a vektor si uložíme do GNU/Octave
A=[1 2;3 3 ]
b=[4; 9]A =
1 2
3 3
b =
4
9
A pro vyřešení soustavy použijeme následující příkaz:
A\bans =
2
1
Výsledek si samozřejmě můžeme uložit do vektoru
x=A\bx =
2
1
A provést ověření, že se rovná vektorů .
A*xans =
4
9
GNU/Octave lze využít, pokud chceme vymyslet příklad na soustavu rovnic, ve které chceme, aby řešením byla celá čísla:
Nejprve si vymyslíme matici, která bude představovat levou stranu soustavy
C=[1 2;4 4]C =
1 2
4 4
A následně si místo pravé strany zvolíme požadované řešení a uložíme ho do sloupcového vektoru (samozřejmě pokud chcete neceločíselné řešení, je možné ho zde také zadat dle potřeby).
x=[5 ; 3]x =
5
3
Následně vynásobíme matice a vektor a obdržíme pravou stranu soustavy (kterou si uložíme do proměnné ).
b=C*xb =
11
32
Pokud chceme vytvořit další příklad, stačí změnit výsledek (tentokrát jej uložíme do vektoru )
y=[3; 5]y =
3
5
A opět vynásobit.
C*yans =
13
32
Toto už nám výrazně urychlí přípravu příkladů. Nicméně ukážeme si ještě jeden způsob, kdy si budeme jednotlivé hodnoty generovat náhodně.
Použijeme k tomu příkaz randi(a,b,c), který slouží pro generování náhodných celých čísel z předem daného parametru. Parametr a je vektor, který udává z jakého intervalu budeme čísla generovat (např. [2 7] bude generovat celá čísla od 2 do pěti (včetně)). Příkaz nám vygeneruje matici, přičemž parametr b určuje počet rádků a parametr c počet sloupců výsledné matice.
%do matice A uloz nahodne hodnoty z intervalu $<-10, 10>$ (prvni parametr zadany jako vektor). Vysledna matice bude mit dva radky (druhy parametr) a dva sloupce (treti parametr)
A = randi([-10 10],2,2)
%do vektoru x ulož náhodné hodnoty z intervalu $<-10, 10>$, vysledny vektor bude mit dva radky a jeden sloupec
x = randi([-10 10],2,1)
% vypocitej pravou stranu rovnice
b=A*xA =
-8 6
9 -5
x =
10
4
b =
-56
70
Při řešení soustav rovnic bychom neměli postupovat bezhlavě. Podívejte se na následujicí soustavu:
D=[1 2 3;3 2 1;4 4 4]
b=[1;1;2]
x=D\bD =
1 2 3
3 2 1
4 4 4
b =
1
1
2
warning: matrix singular to machine precision
x =
0.1667
0.1667
0.1667
Vidíme, že při heldání řešení na nás vyskočilo varování, že je matice singulární (má nulový determinant). Z toho plyne, že jsou řádky matice lineárně závislé (a rovnice tedy má nekonečně mnoho řešení). Toto si můžete ověřit sami pomocí výpočtu determinantu - ten se počítá s využitím funkce det().
D=[1 2 3;3 2 1;4 4 4]
det(D)D =
1 2 3
3 2 1
4 4 4
ans = 0
Podmíněný příkaz IF¶
Podmíněný příkaz IF patří k základním informatickým konstrukcím a umožňuje spustit rozdílný kód v závislosti na vyhodnocení nějakého výrazu.
Podstatu si vysvětlíme na jednoduchém příkladu. Jste s kamarády v restauraci a pijete limonádu. Po dopití několikáté limonády si chcete dát další, ale nejste si jistí, zda si můžete dát ještě jednu nebo musíte jít domů. Navíc domu jedete vlakem, na který zatím nemáte lístek.
V takovém případě budete postupovat následovně. Nejprve si zjistíte následující informace
Podíváte se , kolik máte v peněžence peněz,
Zkontroluje si, kolik limonád jste již vypili,
Podíváte se, kolik jedna limonáda stojí,
A najdete si, kolik stojí cena lístku na vlak.
Následně si ověříte, zde Vaše dosavadní útrata + jedna další limonáda stojí méně, než koli vám v peněžence zbyde po nákupu lístku. Pokud ano, můžete si dát ještě jednu limonádu. Pokud ne, rozloučíte se a jdete na vlak.
Nyní si vše zapíšeme pomocí kódu:
%obsah penezenky v Kc
Penezenka = 200
%cena listku na vlak
Listek = 33
%cena limonady
Cena_limonady=36
%pocet vypitych limonad
Pocet_limonad = 4
%Zaklad podmineneho prikazu IF. Po "if" je uveden vyraz, ktery se bude vyhodnocovat
%vyraz bude pravdivy, pokud mame v penezence dostatek penez, abychom si mohli koupit listek a zaroven dalsi limonadu
if Cena_limonady*(Pocet_limonad+1) < (Penezenka - Listek)
%pokud je prikaz vyhodnocen kladne, spusti se tato vetev programu
%program nam vypise, abychom si dali jeste limonadu
disp('Dej si jeste jednu limonadu!')
%prikazem else se ukoncuje vetev programu, ktera se provede kdyz je vyraz vyhodnocen kladne
else
%zde se uvede vetev programu, ktera bude provedena, pokud je vyraz vyhodnocen zaporne
%program nas informuje, ze musime jit na vlak
disp('Nemas dost penez, bez na vlak')
end
Penezenka = 200
Listek = 33
Cena_limonady = 36
Pocet_limonad = 4
Nemas dost penez, bez na vlak
Program spočítal, že již nemáme dost peněž a máme jít na vlak (tj. výraz byl vyhodnocen negativně a byla spuštěna až větev za else). Upravíme si vstupní parametry, abychom spustili první větev programu:
%obsah penezenky v Kc
Penezenka = 200
%cena listku na vlak
Listek = 33
%cena limonady
Cena_limonady=36
%pocet vypitych limonad
Pocet_limonad = 3
%Zaklad podmineneho prikazu IF. Po "if" je uveden vyraz, ktery se bude vyhodnocovat
%vyraz bude pravdivy, pokud mame v penezence dostatek penez, abychom si mohli koupit listek a zaroven dalsi limonadu
if Cena_limonady*(Pocet_limonad+1) < (Penezenka - Listek)
%pokud je prikaz vyhodnocen kladne, spusti se tato vetev programu
%program nam vypise, abychom si dali jeste limonadu
disp('Dej si jeste jednu limonadu!')
%prikazem else se ukoncuje vetev programu, ktera se provede kdyz je vyraz vyhodnocen kladne
else
%zde se uvede vetev programu, ktera bude provedena, pokud je vyraz vyhodnocen zaporne
%program nas informuje, ze musime jit na vlak
disp('Nemas dost penez, bez na vlak')
%Pomocí end ukoncime podmineny prikaz if. Vse co bude nasledovat se vykona vzdy.
end
Penezenka = 200
Listek = 33
Cena_limonady = 36
Pocet_limonad = 3
Dej si jeste jednu limonadu!
Jak vidíme, pokud jsme dopili třetí limonádu, program nás informuje že můžeme pokračovat v konzumaci.
Někdy se stává, že je možných více možností než dvě. Uvažujme tedy, že mají v nabídce i malou limonádu za sníženou cenu. V takovém případě se nejprve budeme ptát zda máme peníze na velkou limonádu, pokud to nebude stačit tak alespoň na malou a pokud ani potom neuspějeme, tak půjdeme domů. Použijeme konstrukci elseif místo else, díky které spojíme dva if do jendoho
%obsah penezenky v Kc
Penezenka = 200
%cena listku na vlak
Listek = 33
%cena limonady
Cena_limonady=36
%pocet vypitych limonad
Pocet_limonad = 4
%cena male limonady
Cena_male_limonady =20
%Zaklad podmineneho prikazu IF. Po "if" je uveden vyraz, ktery se bude vyhodnocovat
%vyraz bude pravdivy, pokud mame v penezence dostatek penez, abychom si mohli koupit listek a zaroven dalsi limonadu
if Cena_limonady*(Pocet_limonad+1) < (Penezenka - Listek)
%pokud je prikaz vyhodnocen kladne, spusti se tato vetev programu
%program nam vypise, abychom si dali jeste limonadu
disp('Dej si jeste jednu limonadu!')
%prikazem elseif se ukoncuje vetev programu, ktera se provede kdyz je vyraz vyhodnocen kladne.
%Pokud prvni vetev nebyla spustena, vyhodnoti se podminka za prikazem elseif
elseif Cena_limonady*(Pocet_limonad)+Cena_male_limonady < (Penezenka - Listek)
%zde se uvede vetev programu, ktera bude provedena, pokud je prvni vyraz vyhodnocen zaporne a druhy kladne
%program nam vypise, abychom si dali malou limonadu
disp('Dej si malou limonadu!')
%prikazem else se ukoncuje predchozi vetev programu
else
%zde se uvede vetev programu, ktera bude provedena, pokud jsou oba prechozi vyrazy vyhodnoceny negativne
%program nas informuje, ze musime jit na vlak
disp('Nemas dost penez, bez na vlak')
%Pomocí end ukoncime podmineny prikaz if. Vse co bude nasledovat se vykona vzdy.
endPenezenka = 200
Listek = 33
Cena_limonady = 36
Pocet_limonad = 4
Cena_male_limonady = 20
Dej si malou limonadu!
Nyní si ukážeme, jak můžeme podmíněný výraz využít pro řešení kvadratické rovnice. Funkci if použijeme proto, abychom rozhodli zda
Musíme vypočítat dva kořeny (a uložit je do vektoru) - diskriminant je kladný
Vypočítáme pouze jeden kořen - diskriminant je nulový
Vypíšeme, že kořeny leží v komplexních číslech (a uložíme je do vektoru) - diskriminant je záporný
%zadame jednotlive cleny kvadraticke rovnice
a=3
b=4
c=5
%vypocitame si diskriminant a jeho vysledek ulozime do D
D=b^2-4*a*c
%Pomoci "if" urcime, co budeme pocitat
%prvni vyraz se pta, zda je diskriminant kladny
if D>0
%pokud ano, spusti se tato vetev a do vektoru x ulozi koreny hdonoty (povsimnete si hranatych zavorek)
x=[(-b+sqrt(D))/(2*a), (-b-sqrt(D))/(2*a)]
%pokud je prvni vyraz vyhodnocen negativne, je prvni vetev preskocena a program vyhodnocuje druhou podminku, zda je diskriminant nulovy
%!!pozor - pouzivaji se vde rovna se, jedno by prirazovalo hodnotu!!
elseif D==0
%pokud je diskriminant nulovy, spusti se tato vetev a do x se ulozi jeden koren (jiz zde nemame hranate zavorky a ukladame jen jedno cislo)
x=-b/(2*a)
%pokud ani druhy vyraz neni vyhodnocen kladne, spusti se treti vetev (protoze uz tu neni zadna podminka)
else
%Program nejprve vypise, ze koreny lezi vkomplexnich cislech a nasledne je ulozi do promenne x (obdobne jako v prvnim pripade)
disp('Reseni lezi v komplexnich cislech')
x=[(-b+sqrt(D))/(2*a), (-b-sqrt(D))/(2*a)]
enda = 3
b = 4
c = 5
D = -44
Reseni lezi v komplexnich cislech
x =
-0.6667 + 1.1055i -0.6667 - 1.1055i
Možná si teď říkáte, že takovýhle kód je užitečný, ale je otravné pořád přepisovat hodnoty členů kvadratické rovnice (a tím zasahovat do skriptu). Toto je snadno řešitelné pomocí funkce. Funkce funguje obdobně jako skript (tj. můžete ji zavolat z příkazové řádky), ale narozdíl od něj vyžaduje nějaké vstupy a vrací nějaké výstupy.
Představme si, že byste chtěli vytvořit funkci soucet, která bude mít na vstupu dvě čísla a bude vracet jejich součet. Tj. po zavolání soucet(2,5) by nám program vrátil hodnotu 7.
Takovou funkci lze vytvořit následovně. Vytvořte si nový skript a pojmenujte jej soucet.m. Do skriptu uveďte následující a uložte:
function vysledek=soucet(a,b)
vysledek=a+b;
endFunkce je hotová, zkuste nyní zavolat
soucet(2,5)ans = 7
Jak vydíte, funkce dělá přesně to, co jsme chtěli a ani nám moc nezkomplikoval samotný skript. Přibil nám první řádek, kde říkáme že se jedná o funkci, která bude vracet proměnnou vysledek (tj. jakmile funkce dojede nakonec, zobrazí nám to, co bylo uloženo do proměnné výsledek). Za rovná se je uveden název one funkce , tj. soucet a v závorce jsou uvedeny proměnné, se kterými se bude počítat. Náš program potřebuje dva vstupy, které jsme si pojmenovali a a b (ale můžeme je pojemnovat jak chceme).
Jakmile někdo zavolá program, např. pomocí soucet(2,5), do proměnné a se uloží 2, do b se uloží 5 a program se začne vykonávat - konkrétně vysledek=a+b; říká, že do proměnné výsledek se uloží součet a a b. Následně program skončil (což mu říká příkaz end) a jako výstup funce se vypíše obsah proměnné vysledek, tj. 7.
Nyní si stejně upravíme náš skript pro řešení kvadratické rovnice. Vytvoříme tedy nový skript, pojmenujeme jej kvadrat.m a vložíme do něj následující text:
function x=kvadrat(a,b,c)
D=b^2-4*a*c;
if D>0
x=[(-b+sqrt(D))/(2*a), (-b-sqrt(D))/(2*a)];
elseif D==0
x=-b/(2*a);
else
disp('Reseni lezi v komplexnich cislech')
x=[(-b+sqrt(D))/(2*a), (-b-sqrt(D))/(2*a)];
end
endNyní máme hotovou funkci, která očekává tři vstupy (členy kvadratické rovnice) a vrací řešení této rovnice. Pokud spustíme kvadrat(1,5,2), program nám vypíše řešení kvadratické rovnice .
kvadrat(1,5,2)ans =
-0.4384 -4.5616