Está en la página 1de 36

Raices de polinomios

Programacin Numrica

Definicin
Un polinomio de grado n es una expresin de la forma: P(x) = anxn + an-1xn-1 + ... +a1x + a0 Donde an <> 0 Teorema (teorema fundamental del lgebra): Si P(x) es un polinomio de grado n >= 1, entonces P(x) = 0 tiene al menos una raz (posiblemente compleja).

Corolario
Si P(x) es un polinomio de grado n >= 1, entonces existen constantes nicas x1, x2, ... xk, posiblemente complejas, y enteros positivos m1, m2, ..., mk, tales que:

m
i =1

=n

P( x) = an ( x x1 )

m1

( x x2 ) m ...( x xk ) m
2

Mtodo de Horner
Sea P(x) = anxn + an-1xn-1 + ... +a1x + a0 Si bn = an y

bk = ak + bk+1x0 para k = n 1, n 2, ..., 1, 0

Por tanto b0 = P(x0). Ms an, si Q(x) = bnxn1 + bn-1xn-2 + ... +b2x + b1 Entonces P(x) = (x x0) Q(x) + b0

Ejercicios
Evaluar:

P(x) = 2x4 3x2 + 3x 4

en x0 = 2

P(x) = 7x5 + 6x4 6x3 + 3x 4 en x0 = 3

P(x) = 5x6 + 3x4 + 2x2 4x

en x0 = 1

Mtodo de Horner en C
double horner(double p[],int n, double x){ double y = p[0]; int i; for(i = 1; i<n; i++){ y = x*y + p[i]; } return y; } double eval(double p[],int n, double x){ double s = 0; int i; for(i = 0; i<n; i++){ s = s + p[i]*pow(x,n-i-1); } return s; }

Evaluacin de la derivada
Dado que: P(x) = (x x0) Q(x) + b0 donde Q(x) = bnxn1 + bn-1xn-2 + ... +b2x + b1 Derivando P(x) = Q(x)+(x x0)Q(x) En x = x0, P(x0) = Q(x0)

Evaluacin de la derivada en C
void hornerDer(double p[],int n, double x,double &y,double &z){ y = p[0]; z = p[0]; int i; for(i = 1; i<n-1; i++){ y = x*y + p[i]; z = x*z + y; } y = x*y + p[n-1]; }

Mtodo horner
Entrada: grado n, a0, a1, ..., an, x0 Salida: y =P(x0), z = P(x0) 1. 2. 3. 4. 5. 6. 7. y = an //calcule bn para P z = an //calcule bn-1 para Q Para j = n 1, n 2, .... , 1 y = x0*y + aj z = x0*z + y y = x0*y + a0 regresar y, z

Mtodo de Horner en Matlab


function [y,z]=Horner(x,x0) %x es un vector con los coeficientes %de P(x) %regresa en y el polinomio y en z %la derivada evaluados en x0 [muda n] = size(x); y = x(1); %calcule bn para P. z = x(1); %calcule bn-1 para Q for j = 2:n-1, y = x0*y + x(j); z = x0*z + y; end y = x0*y + x(n);

Mtodo de Newton para polinomios


Se puede aplicar el mtodo de Newton para polinomios evaluando el polinomio y su derivada mediante el mtodo de Horner. El esquema sera
P ( xn ) P ( xn ) xn +1 = xn = xn P ' ( xn ) Q ( xn )

Newton para polinomios en C


double NewtonPol(double p[],int n,double x0,double ee, int ni){ int i=0; double f,df,x = x0,error; while(i<ni){ hornerDer(p,n,x,f,df); x = x0 - f/df; error = fabs((x-x0)/x); if(error<=ee) return x; i++; x0 = x; } std::cout << "No solucin en " << i << " pasos\n"; return x; }

La Clase Horner
class Horner{ int n; double a[],y,z; Horner(double[] a1){ n = a1.length; a = a1; } public double val(){return y;} public double der(){return z;} public void evalua(double x0){ y = a[n-1]; z = a[n-1]; for(int j = n-2; j>0; j--){ y = x0*y + a[j]; z = x0*z + y; } y = x0*y + a[0]; } }

Ejemplo de llamada
class HornerMain{ static public void main(String[] args){ double pol[] = new double[5]; // P(x)=2*x^4-3*x^2+3*x-4 pol[0]=-4; pol[1]=3; pol[2]=-3; pol[3]=0; pol[4]=2; Horner h = new Horner(pol); h.evalua(-2); System.out.println(P(-2) = "+h.val()); System.out.println("P(-2) = "+h.der()); } }

Mtodo de Newton
class NewtonPol{ double p,tol; double a[]; NewtonPol(double[] a1, double x0_1,double tol_1){ p = x0_1; a = a1; tol = tol_1; } public double resuelve(){ Horner h=new Horner(a); double f=1, d; while(f>tol){ h.evalua(p); f = h.val(); d = h.der(); p = p - f/d; } return p; } }

Ejemplo
class NewtonHornerMain{ static public void main(String[] args){ double pol[] = new double[5]; pol[0]=-4; pol[1]=3; pol[2]=-3; pol[3]=0; pol[4]=2; NewtonPol h = new NewtonPol(pol,-2,1e-5); System.out.println("raiz = "+h.resuelve()); } }

Mtodo de Mller
Utiliza tres aproximaciones: x0, x1, x2. Determina la siguiente aproximacin x3 encontrando la interseccin con el eje x de la parbola definida por los puntos (x0,f(x0)), (x1,f(x1)), (x2,f(x2)).

x0 x1

x2 x3

Mtodo de Mller
Se considera el polinomio P(x) = a(x x2)2 + b(x x2) + c Se puede encontrar a, b y c resolviendo f(x0) = a(x0 x2)2 + b(x0 x2) + c f(x1) = a(x1 x2)2 + b(x1 x2) + c f(x2) = a(x2 x2)2 + b(x2 x2) + c

Mtodo de Mller
Se llega a
c = f ( x2 )

( x0 x2 ) 2 [ f ( x1 ) f ( x2 )] ( x1 x2 ) 2 [ f ( x0 ) f ( x2 )] b= ( x0 x2 )( x1 x2 )( x0 x1 ) ( x1 x2 ) [ f ( x0 ) f ( x2 )] ( x0 x2 ) [ f ( x1 ) f ( x2 )] a= ( x0 x2 )( x1 x2 )( x0 x1 )

Mtodo de Mller
Para minimizar el error al resolver la cuadrtica P(x) = 0, se calcula x3 con
x3 = x2 2c b + signo(b) b 2 4ac

El proceso se reinicia tomando ahora x1, x2, y x3.

Mller en C
complex<double> muller(double p[], int n, complex<double> x0,complex<double>x1,complex<double>x2,double tol,int ni){ complex<double> q,h,h1,h2,d1,d2,d,b,D,E; int i; h1 = x1 - x0; h2 = x2 - x1; d1 = (horner(p,n,x1) - horner(p,n,x0))/h1; d2 = (horner(p,n,x2) - horner(p,n,x1))/h2; d = (d2 - d1)/(h2 + h1); i = 3; while(i <= ni){ b = d2 + h2*d; D = pow((b*b - 4.0*horner(p,n,x2)*d),0.5); if(abs(b - D) < abs(b + D)) E = b + D; else E = b - D; h = -2.0*horner(p,n,x2)/E; q = x2 + h; if( abs(h) < tol) return q;

Mller en C
x0 = x1; x1 = x2; x2 = q; h1 = x1 - x0; h2 = x2 - x1; d1 = (horner(p,n,x1) - horner(p,n,x0))/h1; d2 = (horner(p,n,x2) - horner(p,n,x1))/h2; d = (d2 - d1)/(h2 + h1); i++; } std:cout <<"Fallo despus de << ni << iteraciones\n"; } int main() { double pol[]={16,-40,5,20,6}; complex<double> x0(0.5,0.0),x1(-0.5,0.0),x2(0.0,0.0); complex<double> raiz = muller(pol,5,x0,x1,x2,0.0001,20); cout << raiz << "\n"; system("PAUSE"); return 0; }

Horner complejo
complex<double> horner(double p[],int n, complex<double> x){ complex<double> y = p[0]; int i; for(i = 1; i<n; i++){ y = x*y + p[i]; } return y; }

Mtodo de Mller en Matlab


% metodo de Muller para obtener una solucin para f(x)=0 function p = muller(f,x0,x1,x2,tol,ni) h1 = x1 - x0; h2 = x2 - x1; d1 = (polyval(f,x1) - polyval(f,x0))/h1; d2 = (polyval(f,x2) - polyval(f,x1))/h2; d = (d2 - d1)/(h2 + h1); i = 3; while i <= ni b = d2 + h2*d; D = (b*b - 4*polyval(f,x2)*d)^0.5; if abs(b - D) < abs(b + D) E = b + D; else E = b - D; end h = -2*polyval(f,x2)/E; p = x2 + h; if abs(h) < tol return; end

Mtodo de Mller en Matlab


x0 = x1; x1 = x2; x2 = p; h1 = x1 - x0; h2 = x2 - x1; d1 = (polyval(f,x1) - polyval(f,x0))/h1; d2 = (polyval(f,x2) - polyval(f,x1))/h2; d = (d2 - d1)/(h2 + h1); i = i + 1; end fprintf('Fallo despus de %d iteraciones',ni);

Ejemplo
P(x) = 16x4 40x3 + 5x2 + 20x + 6

x0 = i 3 4 5 6 7 8

0.5

x1 = -0.5 xi

x2 =

0.0 P(xi) -29.400701 + ( 1.332225 + ( 0.375058 + ( -0.146750 + ( 3.898725)i 1.193097)i 0.670168)i 0.007446)i

-0.555556 + ( -0.598352)i -0.435450 + ( -0.102101)i -0.390631 + ( -0.141852)i -0.357698 + ( -0.169926)i -0.356051 + ( -0.162856)i -0.356062 + ( -0.162758)i

-0.001840 + ( -0.000538)i 0.000002 + ( -0.000001)i

Ejemplo
x0 = i 3 4 5 2.5 x1 = 2.0 xi 1.960592 + ( 1.970564 + ( 1.970447 + ( 0.000000)i 0.000000)i 0.000000)i x2 = 2.3 P(xi) -0.611310 + ( 0.007455 + ( 0.000029 + ( 0.000000)i 0.000000)i 0.000000)i

x0 = i 3 4 5 6

0.5

x1 =

1.0 xi

x2 =

1.5 P(xi)

1.287855 + ( 1.237459 + ( 1.241605 + ( 1.241677 + (

0.000000)i 0.000000)i 0.000000)i 0.000000)i

-1.376275 + ( 0.126945 + ( 0.002193 + ( -0.000001 + (

0.000000)i 0.000000)i 0.000000)i 0.000000)i

Races de no lineales en Matlab


fzero(FUN, x0) encuentra la raz de FUN cerca al punto x0. Ejemplos: FUN puede especificarse usando @: X = fzero(@sin,3) regresa pi. X = fzero(@sin,3,optimset('disp','iter')) regresa pi, usa la tolerancia por omisin y despliega informacin de las iteraciones. FUN puede ser una funcin en lnea: X = fzero(inline('sin(3*x)'),2);

Polinomios con Matlab


polyval(P, x) evalua el polinomio P en el punto x. El polinomio se especifica como un vector donde P(1) es el coeficiente de la potencia ms alta y P(length(P)) es el trmino independiente. polyder(P) obtiene la derivada delpolinomio P. con(A, B) multiplica el polinomio A por el polinomio B. [Q R] = deconv(A, B) divide los dos polinomios A y B y almacena el cociente en Q y el residuo en R. roots(P) encuentra todas las raices reales y complejas del polinomio P.

Mtodo de Bairstow
El enfoque de Bairstow es el de utilizar el Mtodo de Newton para ajustar los coeficientes r y s en la cuadrtica x2 rx + s hasta que sus races sean tambin races del polinomio que se quiere resolver. Con estos coeficientes se determina la cuadrtica correspondiente que se utiliza para simplificar la expresin, eliminando estas races del conjunto buscado. El proceso se repite hasta que el polinomio se convierta en uno cuadrtico o lineal, momento en que todas las races quedan determinadas.

La Divisin Larga de un polinomio


P ( x ) = ai x i
i =0 n

por x2 rx s resulta en un cociente de la forma


Q( x ) = bi x i
i =0 n

y un residuo b1(x r) + b0 tal que


n2 i P( x ) = x rx s bi x + b1 ( x r ) + b0 i=2

Se utiliza la divisin sinttica para obtener la divisin entre el factor cuadrtico: bn = an bn1 = an1 + rbn bi = ai + rbi+1 + sbi+2 (i = n 2,, 0) El mtodo se reduce a determinar los valores de r y s que hacen que el factor cuadrtico sea un divisor exacto. Se utiliza el mtodo de Newton-Raphson. Se calculan incrementos r y s para acercarse a la solucin. b1 b r + 1 s = b1 r s b0 b r + 0 s = b2 r s Las derivadas parciales se calculan por un proceso de divisin sinttica similar al utilizado para calcular las bs.

cn = b n cn1 = bn1 + rcn ci = bi + rci+1 + sci+2 (i = n 2,, 1) Donde:


b1 b , c3 = 1 r s b b c1 = 0 , c2 = 0 r s c1 =

Se resuelven las ecuaciones para r y s y se emplean para mejorar r y s.

Bairstow en C
void bairstow(double a[],int nn,double es, double rr, double ss,int maxit, double re[],double im[],int &ier){ double b[nn],c[nn]; double r=rr,s=ss,det,dr,ds,ea1,ea2,r1,r2,i1,i2; int n=nn,i,iter; ier = 0; ea1 = 1; ea2 = 1; do{ if(n<3 || iter>=maxit)break; iter = 0; do{ iter++; b[n] = a[n]; b[n-1] = a[n-1]+r*b[n]; c[n] = b[n]; c[n-1] = b[n-1]+r*c[n]; for(i = n-2; i>=0; i--){ b[i] = a[i]+r*b[i+1]+s*b[i+2]; c[i] = b[i]+r*c[i+1]+s*c[i+2]; } det = c[2]*c[2]-c[3]*c[1];

if(det!=0){ dr = (-b[1]*c[2]+b[0]*c[3])/det; ds = (-b[0]*c[2]+b[1]*c[1])/det; r = r+dr; s = s+ds; if(r!=0) ea1 = fabs(dr/r)*100; if(s!=0) ea2 = fabs(ds/s)*100; }else{ r++; s++; iter = 0; } if(ea1<=es && ea2<=es || iter>maxit) break; }while(true); Quadroot(r,s,r1,i1,r2,i2); re[n] = r1; im[n] = i1; re[n-1] = r2; im[n-1] = i2; n = n-2; for(i=0; i<=n; i++) a[i] = b[i+2]; }while(1); if(iter<maxit) if(n==2){ r = -a[1]/a[2]; s = -a[0]/a[2];

Quadroot(r,s,r1,i1,r2,i2); re[n] = r1; im[n] = i1; re[n-1] = r2; im[n-1] = i2; }else{ re[n] = -a[0]/a[1]; im[n] = 0; } else ier = 1; } void Quadroot(double r,double s,double &r1,double &i1,double &r2,double &i2){ double disc = r*r+4*s; if(disc>0){ r1 = (r+sqrt(disc))/2.0; r2 = (r-sqrt(disc))/2.0; i1 = 0; i2 = 0; }else{ r1 = r/2.0; r2 = r1; i1 = sqrt(fabs(disc))/2.0; i2 = -i1; } }

Tarea
Escriba un programa en C amigable para el usuario que utilice la funcin bairstow() para encontrar las races de un polinomio. Deber pedir el grado del polinomio, los coeficientes, los valores iniciales para la funcin bairstow, el error esperado y el nmero de iteraciones mximo. Deber dar como salida una lista de las races del polinomio y/o una indicacin de error.

También podría gustarte