Documente Academic
Documente Profesional
Documente Cultură
f (x) = 0
Ecuaţie algebrică – dacă f (x) este polinom.
Ecuaţia transcendentă – în caz contrar.
y y
f(ξ 0)
f(ξ 0)
ξ0 ξ x ξ0 ξ x
(a) (b)
FIGURA 7.1. Cazuri de rădăcini aproximative care nu satisfac simultan criteriile |ξ 0 − ξ| < ε şi
|f (ξ 0 )| < ε.
Determinarea rădăcinilor reale:
Teorema 7.1 Dacă o funcţie continuă f (x) admite valori de semn opus la capetele unui
interval [a, b], adică f (a)f (b) < 0, atunci acel interval conţine cel puţin o rădăcină a
ecuaţiei f (x) = 0.
y y
f(b ) f(b)
f(a)
a
b x a b x
f(a)
(a) (b)
Separarea rădăcinilor:
• Dacă [xm , xm+1 ] sunt suficient de mici, fiecare subinterval va conţine cel mult o
rădăcină.
2
7.2 Metoda bisecţiei (metoda înjumătăţirii)
Fie f (x) continuă pe [a, b] şi fie ecuaţia:
f (x) = 0.
Presupunem că în urma separării rădăcinilor există cel mult o rădăcină ξ ∈ [a, b].
Împărţim [a, b] în mod repetat în părţi egale, păstrând semiintervalul [ai , bi ] la capetele
căruia funcţia are semne opuse.
f(a0)
ξ x0 b = b0
a = a0 x
f(a1)
ξ b1
a1 x1 x
f(b1)
f(a2)
ξ b2
a2 x
f(b2)
3
/*---------------------------- Metoda bisectiei ---------------------------*/
#include <stdio.h>
#include <math.h>
/*=========================================================================*/
float func(float x)
{
return (x+2)*(x+1)*x*(x-1)*(x-2);
}
/*=========================================================================*/
int Bisect(float Func(float), float a, float b, float *x)
/*---------------------------------------------------------------------------
Determina un zero real al unei functii reale prin metoda bisectiei
Func - functia utilizator
a, b - limitele intervalului de cautare
*x - zeroul gasit (iesire)
Returneaza indicele de eroare: 0 - executie normala
1 - nr. maxim de iteratii depasit
2 - intervalul nu contine o radacina
---------------------------------------------------------------------------*/
{
const float eps = 1e-6; /* criteriu relativ de precizie */
const int itmax = 100; /* nr. maxim de iteratii */
float fa, fx;
int it;
/* zeroul este unul din capete ? */
fa = Func(*x=a); if (fabs(fa) <= eps) return 0;
fx = Func(*x=b); if (fabs(fx) <= eps) return 0;
if (fa*fx > 0) return 2; /* intervalul nu contine o radacina */
for (it=1; it<=itmax; it++) {
*x = (a + b)/2; /* noua aproximatie */
fx = Func(*x);
if (fa*fx > 0) a = *x; else b = *x; /* alege noul interval */
if (((b-a) <= eps*fabs(*x)) || (fabs(fx) <= eps)) return 0;
}
printf("Bisect: nr. maxim de iteratii depasit !\n");
return 1;
}
/*=========================================================================*/
void main()
{
float a, b, h, x, xmin, xmax;
printf("xmin = "); scanf("%f",&xmin);
printf("xmax = "); scanf("%f",&xmax);
printf("h = "); scanf("%f",&h);
a = xmin;
while (a < xmax) {
b = a + h;
if ((Bisect(func,a,b,&x) == 0) && (x != b)) printf(" x = %f \n",x);
a = b;
}
}
4
7.3 Metoda poziţiei false (metoda corzii)
În general mai eficientă decât metoda bisecţiei.
Avantajoasă însă tot numai pentru determinarea grosieră a rădăcinilor reale.
f(bi )
ai xi
ξ bi x
y = f(x)
f(ai )
FIGURA 7.4. Împărţirea intervalului de căutare prin intermediul corzii care uneşte punctele
(ai , f (ai )) şi (bi , f (bi )) în cazul metodei poziţiei false.
astfel încât
f (ai+1 )f (bi+1 ) < 0.
5
/*=========================================================================*/
int FalsPos(float Func(float), float a, float b, float *x)
/*---------------------------------------------------------------------------
Determina un zero real al unei functii reale prin metoda pozitiei false
Func - functia utilizator
a, b - limitele intervalului de cautare
*x - zeroul gasit (iesire)
Returneaza indicele de eroare: 0 - executie normala
1 - nr. maxim de iteratii depasit
2 - intervalul nu contine o radacina
---------------------------------------------------------------------------*/
{
const float eps = 1e-6; /* criteriu relativ de precizie */
const int itmax = 100; /* nr. maxim de iteratii */
float dx, fa, fb, fx;
int it;
/* zeroul este unul din capete ? */
fa = Func(*x=a); if (fabs(fa) <= eps) return 0;
fb = Func(*x=b); if (fabs(fb) <= eps) return 0;
if (fa*fb > 0) return 2; /* intervalul nu contine o radacina */
for (it=1; it<=itmax; it++) {
*x = (a*fb - b*fa)/(fb - fa); /* noua aproximatie */
fx = Func(*x);
if (fa*fx > 0) { /* alege noul interval */
dx = *x - a; a = *x; fa = fx;
} else {
dx = b - *x; b = *x; fb = fx;
}
if ((fabs(dx) <= eps*fabs(*x)) || (fabs(fx) <= eps)) return 0;
}
printf("FalsPos: nr. maxim de iteratii depasit !\n");
return 1;
}
6
7.4 Metoda aproximaţiilor succesive
Una dintre metode numerice foarte importante – utilizabilă pt. rafinarea rădăcinilor.
Presupunem că f (x) este continuă pe [a, b] şi se cere rezolvarea ecuaţiei:
f (x) = 0,
Se pune sub forma echivalentă:
x = ϕ(x).
y y
y = ϕ(x)
y = ϕ(x)
x0 x2 ξ x3 x1 x x0 x1 x2 ξ x
(a) (b)
y y
y = ϕ(x)
y = ϕ(x)
x2 x0 ξ x1 x3 x ξ x0 x1 x2 x3 x
(c) (d)
FIGURA 7.5. Procese iterative în metoda aproximaţiilor succesive aplicată ecuaţiei x = ϕ(x)
pentru: a) −1 < ϕ0 (x) < 0; b) 0 < ϕ0 (x) < 1; c) ϕ0 (x) < −1; d) ϕ0 (x) > 1.
Rădăcină reală ξ pt. x = ϕ(x) – abscisa punctului de intersecţie dintre y = ϕ(x) şi y = x.
Procesul este convergent (metoda aplicabilă) numai în intervalele unde
|ϕ0 (x)| < 1.
7
Teorema 7.2 Fie ecuaţia
x = ϕ(x),
cu funcţia ϕ(x) definită şi derivabilă pe [a, b]. Dacă este satisfăcută inegalitatea
xi+1 = ϕ(xi ), i = 0, 1, 2, . . .
converge către rădăcina (unică dacă există) ξ ∈ [a, b] a ecuaţiei, indiferent de valoarea
iniţială x0 .
Cu cât e mai mic λ, cu atât mai rapid converge procesul către rădăcina ξ
Procesul iterativ:
xi+1 = xi − f (xi ), i = 0, 1, 2, . . .
Condiţie de convergenţă:
Corecţia rădăcinii:
∆xi ≡ xi+1 − xi = −f (xi ).
Exemplu:
x − e−x = 0.
ϕ(x) = e−x
|ϕ0 (x)| = e−x < 1.
ϕ(x) = 2x − e−x
|ϕ0 (x)| = 2 + e−x > 1.
8
/*-------------------- Metoda aproximatiilor succesive --------------------*/
#include <stdio.h>
#include <math.h>
/*=========================================================================*/
float func(float x)
{
return x - exp(-x);
}
/*=========================================================================*/
int Iter(float Func(float), float *x)
/*---------------------------------------------------------------------------
Determina un zero real al unei functii reale prin metoda aproximatiilor
succesive
Func - functia utilizator
*x - aproximatie initiala (la intrare), zeroul gasit (la iesire)
Returneaza indicele de eroare: 0 - executie normala
1 - nr. maxim de iteratii depasit
2 - proces divergent
---------------------------------------------------------------------------*/
{
const float eps = 1e-6; /* criteriu relativ de precizie */
const int itmax = 100; /* nr. maxim de iteratii */
float dx, f;
int it;
dx = -Func(*x); /* initializeaza corectia */
for (it=1; it<=itmax; it++) {
f = Func(*x);
if (fabs(f) > fabs(dx)) goto divergent; /* compara noua corectie */
dx = -f; /* actualizeaza corectia */
*x += dx; /* noua aproximatie */
if (fabs(dx) <= eps*fabs(*x)) return 0; /* testeaza convergenta */
}
printf("Iter: nr. maxim de iteratii depasit !\n");
return 1;
divergent:
printf("Iter: proces divergent !\n");
return 2;
}
/*=========================================================================*/
void main()
{
float x;
/* Caz test:
x - exp(-x) = 0, x0 = 0
Zeroul: 0.567143
*/
printf("x0 = "); scanf("%f",&x);
if (Iter(func,&x) == 0) printf("x = %f \n",x);
}
9
7.5 Metoda lui Newton
Metoda Newton-Raphson sau metoda tangentei – eficienţă deosebită.
Presupunem f (x) continuă pe [a, b] şi
f (x) = 0
are o rădăcină reală ξ ∈ [a, b], iar f 0 (x) şi f 00 (x) sunt continue şi păstrează semnul.
y y
y = f(x) y = f(x)
a ξ x0 = a ξ b
x2 x1 x0 = b x x1 x
(a) (b)
f (x0 ) f (x0 )
f 0 (x0 ) = ⇒ x1 = x0 − .
x0 − x1 f 0 (x0 )
Procesul iterativ:
f (xi )
xi+1 = xi − , i = 0, 1, 2, . . .
f 0 (xi )
Funcţia de iterare:
f (x)
ϕ(x) = x − .
f 0 (x)
Condiţia de convergenţă (ca în metoda aproximaţiilor succesive):
Corecţia rădăcinii:
∆xi ≡ xi+1 − xi = −f (xi )/f 0 (xi ).
10
/*=========================================================================*/
int Newton(float Func(float,float *), float *x)
/*---------------------------------------------------------------------------
Determina un zero real al unei functii reale prin metoda Newton-Raphson
utilizand derivata analitica
---------------------------------------------------------------------------*/
{
const float eps = 1e-6; /* criteriu relativ de precizie */
const int itmax = 100; /* nr. maxim de iteratii */
float df, dx, f;
int it;
for (it=1; it<=itmax; it++) {
f = Func(*x,&df); /* functia si derivata */
dx = (fabs(df) > eps) ? -f/df : -f; /* corectia radacinii */
*x += dx; /* noua aproximatie */
if (fabs(dx) <= eps*fabs(*x)) return 0; /* test convergenta */
}
printf("Newton: nr. maxim de iteratii depasit !\n");
return 1;
}
/*=========================================================================*/
int NewtonNumDeriv(float Func(float), float *x)
/*---------------------------------------------------------------------------
Determina un zero real al unei functii reale prin metoda Newton-Raphson
utilizand derivarea numerica
---------------------------------------------------------------------------*/
{
const float eps = 1e-6; /* criteriu relativ de precizie */
const int itmax = 100; /* nr. maxim de iteratii */
float df, dx, f;
int it;
for (it=1; it<=itmax; it++) {
f = Func(*x);
dx = *x ? 1e-4*fabs(*x) : 1e-4; /* pasul de derivare */
df = (Func(*x+dx)-f)/dx; /* derivata numerica */
dx = (fabs(df) > eps) ? -f/df : -f; /* corectia radacinii */
*x += dx; /* noua aproximatie */
if (fabs(dx) <= eps*fabs(*x)) return 0; /* test convergenta */
}
printf("NewtonNumDeriv: nr. maxim de iteratii depasit !\n");
return 1;
}
Exemplu:
x − e−x = 0.
Metoda lui Newton converge în general mai rapid decât metoda aproximaţiilor succesive.
11
7.6 Metoda secantei
Asemănătoare metodei Newton-Raphson – nu necesită evaluarea derivatei funcţiei.
a ξ
x2 x1 x0 = b x
y = f(x)
Tangenta este aproximată de coarda care uneşte punctele pt. două estimări anterioare.
Dezavantaj – rădăcina nu rămâne izolată. Nu este garantată convergenţa.
Din formula metodei Newton-Raphson:
f (xi ) f (xi ) − f (xi−1 )
xi+1 = xi − , f 0 (xi ) ≈
f 0 (xi ) xi − xi−1
Relaţia de recurenţă (implică trei aproximaţii succesive ale rădăcinii):
xi − xi−1
xi+1 = xi − f (xi ) ,
f (xi ) − f (xi−1 )
x1 se poate obţine din x0 aplicând metoda aproximaţiilor succesive:
x1 = x0 − f (x0 ),
/*=========================================================================*/
int Secant(float Func(float), float *x)
{
const float eps = 1e-6; /* criteriu relativ de precizie */
const int itmax = 100; /* nr. maxim de iteratii */
float df, dx, f, f0, x0;
int it;
x0 = *x; f0 = Func(x0);
*x = x0 - f0; /* prima aproximatie */
for (it=1; it<=itmax; it++) {
f = Func(*x);
df = (f-f0)/(*x-x0); /* derivata aproximativa */
x0 = *x; f0 = f; /* memoreaza abscisa si functia */
dx = (fabs(df) > eps) ? -f/df : -f; /* corectia radacinii */
*x += dx; /* noua aproximatie */
if (fabs(dx) <= eps*fabs(*x)) return 0; /* test convergenta */
}
printf("Secant: nr. maxim de iteratii depasit !\n");
return 1;
}
12
Bibliography
[1] J. Ortega şi W. Rheinboldt, Iterative Solution of Nonlinear Equations in Several Vari-
ables (Academic Press, New York, 1970).
[3] Gh. Dodescu, Metode numerice în algebră, Editura tehnică, Bucureşti, 1979).
[4] M. Toma şi I. Odăgescu, Metode numerice şi subroutine, Editura tehnică, Bucureşti,
1980).
[5] B.P. Demidovich şi I.A. Maron, Computational Mathematics (MIR Publishers,
Moskow, 1981).
[6] R.L. Burden şi J.D. Faires, Numerical Analysis, Third Edition (Prindle, Weber &
Schmidt, Boston, 1985).
[7] W.H. Press, S.A. Teukolsky, W.T. Vetterling şi B.P. Flannery, Numerical Recipes in
C: The Art of Scientific Computing, Second Edition (Cambridge University Press,
Cambridge, 1992).