Documentos de Académico
Documentos de Profesional
Documentos de Cultura
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
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:
en x0 = 2
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
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
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; }
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
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)
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.
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.
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.