Oppimateriaalit peruskoulussa ja lukiossa vilisevät yhtälöitä, jotka
on mahdollista ratkaista tarkasti. Monet käytännön ongelmiin liittyvät yhtälöt
eivät kuitenkaan ole ratkaistavissa muuten kuin likimääräisesti. Tällöin astutaan
numeerisen matematiikan pariin. Numeriikka on matematiikan haara, joka käsittelee likiarvoilla laskevia algoritmeja.
Nykyään numeerinen laskenta tehdään luonnollisesti tietokoneella. Oleellista on
tuloksen tarkkuuden lisäksi laskentaan kuluva aika. Vaikkapa tietokonepeleissä näytön tulisi päivittyä lukuisia kertoja sekunnissa, jolloin pikselien oikeat värit täytyy laskea nopeasti. Myöskään sään ennustamisessa ei ole mieltä, jos huomisen ennuste on valmis vasta ensi viikolla.
Nasan simulaatio hurrikaaneista vuodelta 2012. Vapaa ei-kaupallinen käyttö (Wikimedia Commons)
Brute Force
Ratkaistaan yhtälö $4x^4-x^3-5x^2+1=0$. Yhtäpitävästi voidaan ratkaista funktion
$f(x)=4x^4-x^3-5x^2+1$ nollakohdat.
Yksinkertaisin tapa ratkaisuun on laskea suuri määrä funktion arvoja ja katsoa, missä
kohtaa funktion arvo vaihtaa merkkiä. Tämä vastaa oleellisesti ottaen funktion kuvaajan
piirtämistä tietokoneella.
Menetelmää voisi kutsua leikkisästi brute force -menetelmäksi, koska laskenta-aika on
huomattavan suuri saavutettavaan tarkkuuteen nähden.
Esimerkki
Python-koodina laskennan voisi toteuttaa seuraavasti. Neljäs desimaali voi olla väärin
pyöristyksessä syntyvän virheen vuoksi.
def f(x):
return 4*x**4 - x**3 - 5*x**2 + 1
print("Tulostetaan funktion nollakohtien likiarvot:")
x = -2 # Alkuarvo
askelpituus = 0.0001
ylaraja = 2 # Mihin laskenta lopetetaan
f1 = f(x)
while x < ylaraja:
x = x + askelpituus
f2 = f(x)
if f1*f2 < 0 or f2 == 0:
print(round(x,4))
f1 = f2
Puolitushaku löytää jatkuvan funktion nollakohdan kahden erimerkkisen arvon välistä. Jos esimerkiksi $f$ on jatkuva funktio, $a < b$, ja
arvoilla $f(a)$ ja $f(b)$ on eri merkki, Bolzanon lauseen nojalla välillä $]a, b[$ on funktion nollakohta.
Puolitushaussa tarkastellaan funktion merkkiä välin keskipisteen $c =\dfrac{a+b}{2}$ kohdalla. Jos $f(c) = 0$, nollakohta on löytynyt. Jos taas $f(c) \neq 0$, joko luvuilla $f(a)$ ja $f(c)$ tai luvuilla $f(b)$ ja $f(c)$ on eri merkki. Näin voidaan siirtyä tarkatelemaan puolitettua väliä $]a, c[$ tai $]c, b[$.
Tätä toistetaan, kunnes välin pituus $x$-akselilla on pienempi kuin tavoiteltu tarkkuus.
Tehtävä 1
Ratkaisematon
Kirjoita ohjelma, joka ratkaisee funktion $f(x) = x^5 + x^3 - 7$ ainoan nollakohdan puolitushaulla käyttäen alkuarvoja $x = 1$ ja $x = 2$.
Likiarvon virhe tulee olla pienempää kuin $10^{-6}$.
Automaattista tarkistusta varten ohjelman tulee tulostaa jokaisen tutkitun välin keskipiste. Tulostuksen tulisi alkaa
1.5
1.25
ja päättyä riittävän tarkkaan likiarvoon nollakohdalle.
Kirjoita ohjelma tähän:
Newtonin menetelmä
Newtonin menetelmä funktion nollakohdan ratkaisemiseksi perustuu siihen, että derivoituva funktio on pienessä mittakaavassa likimain lineaarinen. Funktion nollakohdan likiarvoksi kelpaa siis funktion tangenttisuoran nollakohta, joka on helpompi laskea.
Newtonin menetelmässä lähdetään liikkeella alkuarvauksesta $x_0$. Tässä kohdassa funktion
$f$ arvo on $f(x_0)$ ja tangentin kulmakerroin $f'(x_0)$. Jos tangentin nollakohta on $x_1$, pätee
\[
f'(x_0) = \dfrac{f(x_0)-0}{x_0-x_1},
\]
josta ratkaistuna
\[
x_1 = x_0-\dfrac{f(x_0)}{f'(x_0)}.
\]
Prosessi voidaan aloittaa alusta pisteestä $x=x_1$, jolloin saadan jono $x_0$, $x_1$, $x_2$... yhä tarkempia likiarvoja nollakohdalle. Yleinen iterointikaava on
\[
x_{n+1} = x_n-\dfrac{f(x_n)}{f'(x_n)}.
\]
Iteroiminen eli toistaminen voidaan lopettaa, kun peräkkäisten muuttujan $x$ arvojen erotus, eli $\dfrac{f(x_n)}{f'(x_n)}$, on riittävän pieni.
Newtonin menetelmä on erittäin nopea silloin kun se toimii. Valitettavasti iteraatio ei kuitenkaan aina suppene. Esimerkiksi derivaatan nollakohtaan osuminen aiheuttaa nollalla jaon, ja toisinaan suppeneminen riippuu sopivan alkuarvon valinnasta.
Tehtävä 2
Ratkaisematon
Kirjoita ohjelma, joka etsii funktion $f(x) = x^5 + x^3 - 7$
ainoan nollakohdan Newtonin menetelmällä käyttäen alkuarvoa $x_0 = 1.5$. Tulos saa poiketa oikeasta tuloksesta korkeintaan $10^{-6}$.
Automaattista tarkistusta varten ohjelman tulee tulostaa alkuarvo ja jokaisen iteraatiokierroksen tulos omille riveilleen. Tulostuksen pitäisi siis alkaa (ainakin likimain)
1.5
1.3762183235867447
ja viimeisellä rivillä tulisi olla riittävän tarkka likiarvo.
Kirjoita ohjelma tähän:
Esimerkki
Newtonin menetelmällä voi ratkaista tehokkaasti likiarvoja esimerkiksi neliöjuurille. Luku $\sqrt{2}$ on nimittäin funktion $f(x)=x^2 - 2$ nollakohta. Derivaataksi saadaan $f'(x)=2x$, joten iterointikaava on
\[
x_{n+1} = x_n-\dfrac{f(x_n)}{f'(x_n)}= x_n-\dfrac{x_n^2-2}{2x_n}.
\]
Tämän voi vielä sieventää muotoon
\[
x_{n+1} = \frac12x_n+\frac{1}{x_n}.
\]
Vaikkapa alkuarvolla $x_0 = 1$ saadaan
\begin{align*}
x_1 &= \frac12x_0+\frac{1}{x_0} = \frac12\cdot 1 +1 = 1.5 \\
x_2 &= \frac12x_1+\frac{1}{x_2} = \frac12\cdot 1.5 +\frac{1}{1.5} = 1.41666... \\
x_3 &= 1.414215686274509...\\
x_4 &= 1.414213562374689...\\
x_5 &= 1.414213562373095...
\end{align*}
Luvussa $x_5$ kaikki esiin kirjoitetut desimaalit ovat jo oikein.
Tehtävä 3
Ratkaisematon
Kirjoita Newtonin menetelmään perustuva algoritmi, joka laskee luvun $\sqrt[3]{2}$ likiarvon. Virhe saa olla korkeintaan $10^{-9}$. Kuten aiemmassa esimerkissä, algoritmi saa käyttää vain yhteen-, vähennys-, kerto- ja jakolaskua.