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 05

V této lekci si ukážeme, jak s dostatečnou přesností vypočítat obsah plochy pod křivkou (vyjdeme z poznatků z matematické analýzy).

Výpočet obsahu plochy pod funkcí sin(x)sin (x)

Našim prvním úkolem bude spočítat obsah plochy pod funkcí sin(x)sin(x) na intervalu 0,π2\langle 0, \frac{\pi}{2}\rangle.

octave

Na hodinách matematické analýzi jste si jistě ukazovali, jak lze určit plochu pod funkci vepisováním obdélníku o stejné délce. Počítal se horní a dolní odhad a bylon zřejmé, že skutečná plocha bude někde mezi těmito hodnotami.

My použijeme podobný postup, ale místo hodního a dolního odhadu budeme počítat jen jeden.

octave

Jak je patrné z obrázku, místo toho, abysme jednotlivé obdélníky konstruovali tak, že budou všechny pod (nebo nad) funkcí (což by bylo náročné na výpočty), spočítáme funkční hodnotu “uprostřed” šířky obdélníku, a tuto hodnotu použijeme jako výšku obdélníku. Tímto se výpočet výrazně sníží. Navíc počítač nebude mít problém těchto obdélníků spočítat opravdu velké množství (o malé šířce) a tím aproximovat plochu s dostatečnou přesností.

Co tedy musíme vypočítat?

  1. Na základě zvoleného počtu obdélníku NN musíme rozdělit zvolený interval na N+1N+1 bodů, které budou stejně daleko od sebe.

  2. Musíme zjistit šířku obdélníku.

  3. Ve “středu” šířky každého obdélníku musíme zjistit funkční hodnotu funkce sin(x)sin(x).

  4. Spočítáme plochu jednotlivých obdélníků a následně tyto plochy sečteme.

1. Jak rozdělit interval na stejně velké úseky

Pokud chceme rozdělit například následující interval 0,90\langle 0, 90\rangle na 9 stejně dlouhých úseků, lze využít následující kód:

x=0:10:90
x =

    0   10   20   30   40   50   60   70   80   90

Ovšem pokud bychom stejný interval chtěli rozdělit na 8 stejných úseků, bylo by to již náročnější. Museli bychom spočítat, že délka kroku je 11,2511,25

x=0:11.25:90
x =

 Columns 1 through 7:

          0    11.2500    22.5000    33.7500    45.0000    56.2500    67.5000

 Columns 8 and 9:

    78.7500    90.0000

Obecně pro rozdělení intervalu a,b\langle a, b \rangle na N stejných úseků, museli bychom použít následující vzorec pro zjištění šířky jednoho úseku:

baN\frac{b-a}{N}

Pokud bychom tedy interval 0,π2\langle 0, \frac{\pi}{2}\rangle chtěli rozdělit na 9 stejně velkých úseků, museli bychom spočítat

baN=π209=π18\frac{b-a}{N}=\frac{\frac{\pi}{2}-0}{9}=\frac{\pi}{18}

a tedy

x=0:pi/18:pi/2
x =

 Columns 1 through 8:

         0    0.1745    0.3491    0.5236    0.6981    0.8727    1.0472    1.2217

 Columns 9 and 10:

    1.3963    1.5708

Protože by nás takové výpočty jen zdržovali, využijeme funkce linspace(a,b,c), která tyto výpočty provedene za nás. Parametr a je levá strana intervalu, parametr b je pravá strana intervalu a c značí počet bodů (nezapomeňte, že počet bodů je o 1 větší než je počet úseků).

x=linspace(0,pi/2,10)
x =

 Columns 1 through 8:

        0   0.1745   0.3491   0.5236   0.6981   0.8727   1.0472   1.2217

 Columns 9 and 10:

   1.3963   1.5708

Pomocí příkazu linspace() jsem si tedy rozdělili interval na stejně dlouhé úseky-

2. Zjištění šířky obdélníku.

Interval jsem si v přechozím kroce rozdělili na stejné úseky, šířka všech obdélníků je tedy stejná. Zůstává otázkou, jak ji spočítat.

Protože jednotlivé body intervalu jsou uloženy v proměnné xx, bude stačít najít dvě sousední hodnoty a odečíst menší od větší a výsledek uložit do proměnné delta.

Pomocí x(i) zjistíme i-tou hodnotu vektoru xx, proto stačí napsat:

delta=x(2)-x(1)
delta = 0.1745

Nemusíme nutně brát první dvě hodnoty, stačí libovolné jiné dvě po sobě jdoucí.

3. Zjištění funkční hodnotu funkce sin(x)sin(x) ve “středu” šířky každého obdélníku

Nyní je třeba zjistit funkční hodnoty funkce sin(x)sin(x) “uprostřed” šířky jednotlivých obdélníků. Abyhcom toto mohli udělat, musíme nejprve zjistit střed šířky.

Ukážeme si to na prvním obdélníku. Ten začíná v bodě 0 a končí v bodě 0.1745. Mohli bychom tedy střed zjistit pomocí rozdílu krajních hodnot, ale jednodušší bude k počátečnímu bodu přičíst polovinu šířky obdelníku:

x(1)+delta/2
ans = 0.087266

U druhého obdélníku bychom postupovali obdobně

x(2)+delta/2
ans = 0.2618

A to stejné u třetího

x(3)+delta/2
ans = 0.4363

Z výše uvedého je vidět, že určení středu je poměrně přímočaré a abychom nemuseli všechny výpočty vypisovat, budeme muset použít cyklus for. Pokud by nám šlo pouze o středy obdélníků, vypadala by funkce následovně (pozor, zajímají nás jen počáteční body obdélníku, proto je v cyklu uvedeno 9 místo 10!):

for i=1:1:9
    x(i)+delta/2
end
ans = 0.087266
ans = 0.2618
ans = 0.4363
ans = 0.6109
ans = 0.7854
ans = 0.9599
ans = 1.1345
ans = 1.3090
ans = 1.4835

Když už víme jak určit středy šířky, zbývá nám v těchto bodech spočítat funkční hodnoty funkce sin(x)sin(x). Přidáme tedy k předchozímu kódu funkci sinus:

sin(x(1)+delta/2)
ans = 0.087156

A pro všechny hodnoty s využitím cyklu for použijeme

for i=1:1:9
    sin(x(i)+delta/2)
end
ans = 0.087156
ans = 0.2588
ans = 0.4226
ans = 0.5736
ans = 0.7071
ans = 0.8192
ans = 0.9063
ans = 0.9659
ans = 0.9962

4. Výpočet plochy jednotlivých obdélníků a následný součet těchto ploch

Když známe šířky obdélníků i jejich výšky (funkční hodnoty ve středech šířky), můžeme již vypočítat plochy jednotlivých obdélníků. Opět si to ukážeme na příkladu prvního obdélníku.

%delta odpovída sirce
%sin(x(1)+delta/2) odpovida vysce
%jejich vynasobenim dostavame plochu obdelniku

delta*sin(x(1)+delta/2)
ans = 0.015212

Opět využijeme cyklus for, abychom provedli výpočet pro všechny obdélníky

for i=1:1:9
    delta*sin(x(i)+delta/2)
end
ans = 0.015212
ans = 0.045172
ans = 0.073761
ans = 0.1001
ans = 0.1234
ans = 0.1430
ans = 0.1582
ans = 0.1686
ans = 0.1739

Dostali jsme tedy plochy jednotlivých obdélníků. Poslední co musíme udělat, je tyto hodnoty sečíst. Jendou z možností by bylo hodnoty uložit do vektoru a následně je sečíst. My ovšem použijeme přímočařejší přístup. Nejprve si vytvoříme proměnnou plocha kterou položíme rovnu jedné a následně v každém kroku cyklu for k této hodnotě přičteme vypočtený obsah obdélníku:

plocha=0

for i=1:1:9
    plocha=plocha+delta*sin(x(i)+delta/2)
end
plocha = 0
plocha = 0.015212
plocha = 0.060384
plocha = 0.1341
plocha = 0.2343
plocha = 0.3577
plocha = 0.5006
plocha = 0.6588
plocha = 0.8274
plocha = 1.0013

Nyní vše spojíme do jednoho kódu a máme hotovo. Kód jsme vylepšili tím, že do NN na začátku zadáváme počet bodů, na které si interval rozdělíme (tj. budeme mít N-1 obdélníků) a toto NN pak používáme jak ve funkci linspace tak v cyklu for. Změnou hodnoty v NN tedy upravíme přesnost celého výpočtu.

N=4000

x=linspace(0i,pi/2,N);
delta=x(2)-x(1)

plocha=0

for i=1:1:N-1
    plocha=plocha+delta*abs(sin(x(i)+delta/2));
end

plocha
N = 4000
delta = 3.9280e-04
plocha = 0
plocha = 1.0000

Pokud budeme chtít vypočítat hodnotu funkce na intervalu 0,π\langle 0, \pi \rangle, stačí jen upravit meze ve funkci linspace

n=4000

x=linspace(0,pi,n);
delta=x(2)-x(1)

plocha=0

for i=1:1:n-1
    plocha=plocha+delta*abs(sin(x(i)+delta/2));
end

plocha
n = 4000
delta = 7.8559e-04
plocha = 0
plocha = 2.0000

Pojďme spočítat plochu na intervalu 2π,2π\langle -2\pi, 2\pi \rangle.

n=4000

x=linspace(-2*pi,2*pi,n);
delta=x(2)-x(1)

plocha=0

for i=1:1:n-1
    plocha=plocha+delta*sin(x(i)+delta/2);
end

plocha
n = 4000
delta = 3.1424e-03
plocha = 0
plocha = 1.0381e-15

Výsledkem je číslo, které je velmi blízko nule. Tento výsledek je správně, protože určitý intergrál na tomto intervalu opravdu je 0 (je to způsobeno tím, že funkce sin(x)sin(x) má na daném intervalu stejnou plochu nad i pod osou xx).

Pokud bychom ovšem chtěli znát celkovou plochu, můžeme kód doplnit o absolutní hodnotu a tím vše vyřešit:

n=4000

x=linspace(-2*pi,2*pi,n);
delta=x(2)-x(1)

plocha=0

for i=1:1:n-1
    plocha=plocha+abs(delta*sin(x(i)+delta/2));
end

plocha
n = 4000
delta = 3.1424e-03
plocha = 0
plocha = 8.0000

Výpočet obsahu ploch pod jinou funkcí

Pokud bychom chtěli najednou počítat plochu pod jinou funkcí, museli bychom zasáhnout do našeho kódu a vše upravit. Změna na cos(x)cos(x) by bylajendoduchá, jen by se změnila funkce sin na cos a bylo by vystaráno.

Co ovšem dělat v situaci, kdy budeme chtít třeba následující funkci x2x3+πe7x^2-\frac{x}{3}+\pi-e^7? Toto by již byla náročnější úprava, protože x(i)+delta/2) bychom museli zadávat dvakrát a výsledný kód by vypadal takto:

n=4000

x=linspace(-2*pi,2*pi,n);
delta=x(2)-x(1)

plocha=0

for i=1:1:n-1
    plocha=plocha+abs(delta*((x(i)+delta/2)^2-(x(i)+delta/2)/3+pi-exp(7)));
end

plocha
n = 4000
delta = 3.142378248151445e-03
plocha = 0
plocha = 13575.85348058021

Nabízí se tedy otázka, jak toto vyřešit elegantněji. Naštestí existují anonymní funkce, které tento problém řeší.

Anonymní funkceumožňují velmi jednoduchým způsobem zadefinovat libovolnou funkci.

Pokud bychom potřebovali funkci treti_mocnina, která libovolné číslo umocní na třetí, použili bychom následující kód:

treti_mocnina=@(x) x^3
treti_mocnina =

@(x) x ^ 3

Před rovná se je uveden název funkce, symbol @ zančí , že se jedná o anonymní funkci a do závorky se za něj píšou vstupní proměnné - v našem případě máme jednu vstupní proměnnou a označili jsme si ji xx. následuje již samotný výpočet.

Když nyní do funkce zadáme libovolné číslo, obdržíme jeho třetí mocninu:

treti_mocnina(3)
ans = 27

Ještě jedna ukázka anonymní funkce

nesmysl=@(x) sin(x)-cos(x)

nesmysl(5)
nesmysl =

@(x) sin (x) - cos (x)

ans = -1.242586460126365

Tato funkce pro libovolnou hodnotu spočíta rozdíl jejího sinu a cosinu.

S využitím těchto poznatků upravím naši funkci pro výpočet plochy tak, že na začátku si zadefinujeme funkci s využítím anonymní funkce a následně jen upravíme zbytek kódu tak, aby použil při výpočtu onu anonymní funkci.

n=4000

funkce=@(x) x.^2-x./3+pi-exp(7)


x=linspace(-2*pi,2*pi,n);
delta=x(2)-x(1)

plocha=0

for i=1:1:n-1
    plocha=plocha+delta*abs(funkce(x(i)+delta/2));
end

plocha
n = 4000
funkce =

@(x) x .^ 2 - x ./ 3 + pi - exp (7)

delta = 3.142378248151445e-03
plocha = 0
plocha = 13575.85348058021

Pokud tedy budeme chtít spočítat obsah plochy pod křivkou pro libovolnou funkci, stačí tuto funkci zadat na začátku programu (a stejně tak bude třeba upravit meze dle potřeby).