Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Lekce 02

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é aa uložit hodnotu, použíjeme symbol ==.

a=7
a = 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
vektor
vektor =

   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)=1
vektor =

   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)=2
vektor =

   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:

1x+2y=41x + 2y = 4

3x+3y=93x + 3y = 9

využijeme toho, že lze soustavu zapsat maticově:

Ax=bA\cdot \vec x = \vec b

kde

A=(1232)A=\begin{pmatrix} 1 & 2 \\ 3 & 2 \end{pmatrix}, x=(xy)x = \begin{pmatrix} x \\ y \end{pmatrix} a b=(49)b=\begin{pmatrix} 4 \\ 9 \end{pmatrix}.

Matici AA a vektor bb 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\b
ans =

   2
   1

Výsledek si samozřejmě můžeme uložit do vektoru xx

x=A\b
x =

   2
   1

A provést ověření, že AxA\cdot x se rovná vektorů bb.

A*x
ans =

   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 xx (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 CC a vektor xx a obdržíme pravou stranu soustavy (kterou si uložíme do proměnné bb).

b=C*x
b =

   11
   32

Pokud chceme vytvořit další příklad, stačí změnit výsledek (tentokrát jej uložíme do vektoru yy)

y=[3; 5]
y =

   3
   5

A opět vynásobit.

C*y
ans =

   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*x
A =

  -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\b
D =

   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.
end
Penezenka = 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

  1. Musíme vypočítat dva kořeny (a uložit je do vektoru) - diskriminant je kladný

  2. Vypočítáme pouze jeden kořen - diskriminant je nulový

  3. 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)]
end
a = 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;

end

Funkce 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

end

Nyní 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 x2+5x+2=0x^2+5x+2=0.

kvadrat(1,5,2)
ans =

  -0.4384  -4.5616