Laboratorium 6: Funkcje. Metoda Newtona-Raphsona

Postawienie problemu

Załóżmy, że mamy wyznaczyć pierwiastek stopnia n z liczby w, czyli znaleźć taką liczbę x, że: xn=w lub inaczej: xnw=0 Jeżeli oznaczymy f(x)=xnw to zadanie to można zapisać ogólniej: należy znaleźć takie x, że f(x)=0.

Jeżeli zadanie dodatkowo uprościmy zakładając:

  • funkcja ma dokładnie jedno miejsce zerowe,

  • jest różniczkowalna,

  • jej pochodna w całym przedziale jest albo dodatnia albo ujemna;

to możemy naszkicować rysunek (rys. 1) ilustrujący nasze zadanie.

Przykład funkcji spełniającej założenia oraz ilustracja pierwszych kroków algorytmu
Przykład funkcji spełniającej założenia oraz ilustracja pierwszych kroków algorytmu

Zaczynamy w punkcie g; wartość funkcji w tym punkcie wynosi f(g). Musimy w jakiś sposób zdecydować w którym kierunku należy wykonać następny krok. Zauważmy, że możemy w tym celu wykorzystać pochodną (czerwona, przerywana linia na poprzednim rysunku). Jeżeli przybliżymy funkcję za pomocą pochodnej (stycznej do) funkcji, przechodzącej przez punk (g,f(g)) to następnym przybliżeniem miejsca zerowego będzie punkt przecięcia stycznej z osią x.

Z równania prostej mamy: f(g)0gg=f(g) czyli f(g)f(g)=gg i dalej g=gf(g)f(g)

Jeżeli zauważymy, że f(x)=xnw oraz, że f(x)=nxn1 to kolejne przybliżenie wyliczane będzie ze wzoru: g=ggnwngn1 albo g=ngngn+wngn1=(n1)gn+wngn1=1n((n1)g+wgn1)

Gdy n=2, wówczas g=12(g+wg).

Istotą algorytmu jest powtarzanie powyższych kroków „w nieskończoność". Procedura jest asymptotycznie zbieżna i umawiamy się, że program kończy pracę gdy kolejna poprawka g nie różni się zbytnio od poprzednio wyliczonej wartości g, czyli |gg|<ε albo gdy wartość funkcji w punkcie g nie różni się zbytnio od zera (|f(g)|<δ). Można stosować oba te kryteria:

  • łącznie — połączone spójnikiem logicznym AND,

  • które „zadziała" pierwsze (spójnik logiczny OR).

Realizacja programowa

Program będzie się składał z trzech części (funkcji):

  1. blisko(g, gprim) — funkcja o wartościach logicznych sprawdzająca czy |gg|ε,

  2. lepszy(n, w, g) — funkcja rzeczywista wyliczająca następne, lepsze przybliżenie pierwiastka,

  3. pierwiastek(n, w, g) — funkcja (rzeczywista) wyliczająca pierwiastek stopnia n z w zaczynając od przybliżenia g.

  4. i, oczywiście, funkcji main.

Uwaga: Dalszy przykład zakłada n=2.

Na kolejnych rysunkach przedstawione są schematy blokowe poszczególnych funkcji. Funkcja pierwiastek realizowana jest w sposób rekurencyjny, ale można z rekurencji zrezygnować i obliczenia przeprowadzać w pętli (na przykład while).

Kod do wykorzystania znajduje się w bryku na stronach 104 i następnych.

Schemat blokowy funkcji lepszy()

Start
return 0.5*(g+w/g);
Koniec

Schemat blokowy funkcji blisko()

N
T
Start
fabs(g-gprim) <= EPS
return FALSE
return TRUE
Koniec

Schemat blokowy rekurencyjnej wersji funkcji pierwiastek()

T
F
Start
gprim=lepszy(w,g)
blisko(g,gprim)
return gprim
return pierwiastek(w,gprim)
Stop

W tym przypadku rekurencja realizuje pętlę: każde wywołanie funkcji rozpoczyna wykonanie jej kodu od początku (z nowymi wartościami zmiennych). Rekurencję można zastąpić zwykłą pętlą…

Schemat blokowy funkcji main()

Start
wprowadź w
ustal 1. przybliżenie g
wynik=pierwiastek(w,g)
wydrukuj wynik
Koniec

Zadania do wykonania

  1. Zaprogramować metodę Newtona-Raphsona dla n=2. Przetestować jej działanie.

  2. Zmodyfikować schematy blokowe i programy aby metoda mogła działać dla dowolnego n (Uwaga: n nie musi być całkowite!). Przetestować.

Program może być rekurencyjny lub nie.

Uwaga

Gdy zachodzi wyliczenie potęgi1 xy można użyć funkcji pow():

#include <math.h>
...
z = pow(x, y);

  1. Wiem, że mając tę funkcję nie trzeba w zawily sposób wyliczać pierwiastka. Ale celem tych zajęć nie jest wyliczenie pierwiastka, tylko zaprojektowanie stosunkowo prostego algorytmu w podziale na funkcje. ↩︎

Poprzedni
Następny