De tweede numerieke methode lost een ander soort probleem op: het zoeken van een nulwaarde van een functie, dus een \(x\)-waarde waarvoor de functie gelijk is aan 0.
Welk getal \(x\) heeft de eigenschap dat \(2^x\) gelijk is aan \(x^2\)?
Je ziet snel twee oplossingen: \(x = 2\) (want \(2^2 = 4\) en \(2^2 = 4\)) en \(x = 4\) (want \(2^4 = 16\) en \(4^2 = 16\)). Maar er is nog een derde oplossing, en die is niet zo netjes.
Teken je de grafieken van \(f(x) = 2^x\) en \(g(x) = x^2\) in hetzelfde assenstelsel, dan snijden ze elkaar op drie plaatsen. Twee snijpunten liggen bij \(x = 2\) en \(x = 4\); het derde ligt links van de \(y\)-as, bij een \(x\) net iets kleiner dan \(-0{,}75\). We willen die derde oplossing graag bepalen tot 12 cijfers na de komma.
Een snijpunt van \(2^x\) en \(x^2\) is precies een nulwaarde van het verschil \(x^2 - 2^x\): daar is \(x^2 - 2^x = 0\), dus \(x^2 = 2^x\). Een nulwaarde zoeken en een snijpunt zoeken is dus hetzelfde.
Voor zo’n nulwaarde bestaat een eenvoudige numerieke methode, de bisectiemethode (van het Latijnse bisectio, “in tweeën snijden”). Ze werkt zo:
Voor ons probleem starten we met het interval \([-1, 0]\). De opeenvolgende intervallen worden dan \([-1, 0]\), \([-1, -0{,}5]\), \([-1, -0{,}75]\), \([-0{,}875, -0{,}75]\), \([-0{,}8125, -0{,}75]\), … Elk interval is half zo groot als het vorige en deelt één eindpunt met het vorige, soms het linker, soms het rechter.
In de figuur hieronder zie je elk interval als een balk op dezelfde getallenlijn. Het verticale streepje is telkens het midden van dat interval; de oranje stippellijn is de gezochte nulwaarde. Merk op hoe elke balk half zo breed is als de vorige en hoe ze stap na stap nauwer rond de nulwaarde sluiten.
We moeten telkens de helft kiezen die de nulwaarde bevat, maar die nulwaarde kennen we net nog niet. Gelukkig weten we wel iets over de ligging van de twee krommen:
Onderstaande figuur zoomt in op het startinterval \([-1, 0]\). Hier kruisen de twee krommen elkaar wél zichtbaar, precies in de nulwaarde. Links daarvan ligt \(x^2\) (blauw) boven \(2^x\) (rood), rechts eronder. Voor het midden \(-0{,}5\) zie je de twee functiewaarden als stippen: \(x^2 = 0{,}25\) ligt onder \(2^x \approx 0{,}71\), dus daar geldt \(x^2 < 2^x\) en zit het midden rechts van de nulwaarde.
Om te weten aan welke kant van de nulwaarde het midden ligt, vergelijken we gewoon de twee functiewaarden \(x^2\) en \(2^x\) in het midden:
Dit zijn de eerste stappen, vertrekkend van \([-1, 0]\):
| Interval | midden | $$x^2$$ in midden | $$2^x$$ in midden | $$x^2 > 2^x$$ ? | nieuw interval |
|---|---|---|---|---|---|
| [-1, 0] | -0.5 | 0.25 | 0.7071 | nee → rechts opschuiven | [-1, -0.5] |
| [-1, -0.5] | -0.75 | 0.5625 | 0.5946 | nee → rechts opschuiven | [-1, -0.75] |
| [-1, -0.75] | -0.875 | 0.7656 | 0.5452 | ja → links opschuiven | [-0.875, -0.75] |
| [-0.875, -0.75] | -0.8125 | 0.6602 | 0.5693 | ja → links opschuiven | [-0.8125, -0.75] |
Het interval knijpt zo stap voor stap samen rond de nulwaarde (ongeveer \(-0{,}7667\)).
We willen 12 cijfers na de komma juist hebben. Dan moet het interval kleiner
worden dan \(10^{-13}\) (we nemen er een cijfer marge bij). Zulke heel kleine
kommagetallen schrijf je handig in wetenschappelijke notatie: in plaats van
0.0000000000001 schrijf je 1E-13. Zo betekent 1.2E23 het getal
\(1{,}2 \times 10^{23}\), en 1E-6 het getal \(0{,}000001\).
De lus draait dus zolang rechts - links groter is dan 1E-13.
Voor de nulwaarde van \(2^x = x^2\) in het interval \([-1, 0]\) ziet dat er zo uit:
double links, rechts, midden;
links = -1.0;
rechts = 0.0;
while (rechts - links > 1E-13)
{
midden = (links + rechts) / 2;
if (Math.Pow(midden, 2) > Math.Pow(2.0, midden))
{
links = midden; // midden ligt links van de nulwaarde
}
else
{
rechts = midden; // midden ligt rechts van de nulwaarde
}
}
Console.WriteLine("het nulpunt= " + links);
Math.Pow(midden, 2) is \(x^2\) in het midden, en Math.Pow(2.0, midden) is
\(2^x\) in het midden. De voorwaarde Math.Pow(midden, 2) > Math.Pow(2.0, midden)
test dus precies of \(x^2 > 2^x\).
De bisectiemethode werkt voor élke functie die je in een gekend interval van teken ziet veranderen: kies een startinterval rond de nulwaarde, halveer telkens, en hou de helft over waarin het teken nog wisselt. Je hoeft de functie zelf niet op te lossen, enkel te kunnen uitrekenen.
In de volgende twee oefeningen pas je deze methode toe.