Está en la página 1de 6

Evaluación de polinomios: Algoritmo de

Horner
Última actualización el Sábado, 18 de Septiembre de 2010 11:25

Estamos tan acostumbrados a ver los polinomios expresados como suma de monomios,

por ejemplo.. pero ¿Y si necesitamos evaluar un polinomio una y otra vez para montones de valores distintos de x? Vamos a plantearnos cómo hacerlo lo mejor posible con la ayuda del esquema de Horner. y en efecto Horner lo describió. vamos calculando el primer monomio: primero sacamos 73. y luego lo sumamos todo. Ese número es el grado del monomio. El algoritmo de Horner propone una forma de evaluar los polinomios descritos como una suma de monomios. Esto no supone mayor problema cuando evaluamos un polinomio sencillito para un solo valor. como de costumbre con un enfoque básico. El algoritmo se basa en el Esquema de Horner. se sabe que el algoritmo había sido utilizado con anterioridad . cuando x vale 7. un poco de análisis y reflexión permiten construir algoritmos más eficientes. Simplemente pretendemos ilustrar cómo a veces. 5. y lo multiplicamos por -2. Cada monomio es un coeficiente que multiplica a una variable x. un matemático inglés del siglo XIII. -2. como x=7. Tomemos como ejemplo el que hemos comentado al principio: P(x)=3x3-2x2+5x-1 Este polinomio está compuesto de cuatro monomios. 3} .. Por ejemplo para evaluar un polinomio como P(x)=3x3-2x2+5x-1. y lo multiplicamos por 3. más conocido por la invención del zootropo . Para representar a un polinomio. luego 72. Pero hablaremos luego del esquema de Horner.. que está elevada a un número. Digo atribuido porque aunque el algoritmo lleva su nombre. podemos utilizar cualquier tipo de lista o vector que nos permita almacenar los coeficientes. como de costumbre) double[] coeficientes={-1.que cuando tenemos que implementar un algoritmo para evaluarlos tendemos a interpretar tal cual la expresión y a codificarla tal y como lo haríamos a mano con ayuda de una calculadora. una forma de reescribir los polinomios atribuida a William George Horner .. un aparato que mostraba imágenes creando la ilusión de animación. ésta: (vamos a utilizar C#. Primero veamos cómo evaluaríamos un polinomio genérico sin conocer el esquema de Horner. así sucesivamente. El primer monomio es de grado 3 y el último es de grado 0.

En el caso del ejemplo.15) . y //la calculamos incluso para aquellos coeficientes //que pudieran ser 0. si nuestro polinomio fuera de grado 15.. int y) { double resultado=1. vamos a calcular el valor del polinomio para un valor cualquiera de x. Después. resultado += coeficientes[i] * potencia(x. corresponde con la posición del vector. Bien. i--) { //La operación potencia puede ser bastante costosa. x3.. Bien. porque así tenemos el coeficiente del monomio de grado 0 en la componente 0 del vector. Ningún programador elegante haría semejante barbaridad. luego x2. En cada invocación. i). se calcula una potencia de x. ya que en cada llamada a potencia se entra en un bucle que multiplica x por sí mismo un determinado número de veces. } return resultado.Almacenamos los coeficientes al revés de como se escribe el polinomio. i >= 0. } return resultado. i++) { resultado *= x. quizá fuera conveniente definirnos un método o función para calcular una potencia.. multiplicando cada coeficiente por la potencia de x elevado al grado del monomio correspondiente. Empezamos por el de mayor grado //y vamos bajando (daría igual al reves) for (int i = grado. private double potencia(double x. //en cada iteración calculamos un monomio //y sumamos. y el coeficiente del monomio de grado 3 en la posición 3 del vector. Como vamos a tener que elevar x al cuadrado y también al cubo. que por la forma en la que hemos almacenado los coeficientes. } //Calculando cada monomio y sumándolos public double evaluar(double x) { double resultado = 0. basta con ir recorriendo el vector. luego x1 y luego x0.. ¿Por qué? Pues porque invocamos varias vaces al método potencia. i <= y. programémoslo: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 //NOTA: ESTE ALGORITMO NO ES MUY BUENO //este metodo calcula la potencia de x elevado a y //multiplicando y veces x por si mismo.. nos daremos cuenta rápidamente de que el algoritmo no es muy bueno. } Si nos paramos un momento a pensar las operaciones de suma y producto que estamos haciendo. for (int i = 1. Es decir.. una llamada a potencia(x.

Si el polinomio fuera mayor. Es decir.. para nuestro polinomio de ejemplo. Aquí es donde entra el algoritmo de Horner. Ahora cojamos el interior del paréntesis (nos dejamos la x que multiplica en el mismo lado que nos dejamos el -1). i <= grado. Vamos a retomar nuestro polinomio de ejemplo P(x)=3x3-2x2+5x-1. pot *= x. En lugar de utilizar ese método potencia sería más adecuado utilizar una variable que en cada vuelta del bucle del método evaluar fueramos multiplicando por sí misma.. con éste algoritmo de arriba. se realizan cuatro vueltas del bucle..14) de la iteración siguiente volvería a multiplicar x por sí mismo 14 veces. } Mucho mejor. Empezamos por el de grado 1 y vamos //subiendo for (int i = 0. pero con el primero se realizan ¡¡¡ 134 multiplicaciones y 15 sumas !!! Como ves. así que 8 multiplicaciones y cuatro sumas. y volvamos a separar el coeficiente que no multiplica a x (y nuevamente lo dejamos a un lado). i++) { //Vamos calculando la potencia de x a memedida //que vamos calculando los monomios. resultado += coeficientes[i] * pot. se realizaban 13 multiplicaciones y cuatro sumas. y lo vamos a dejar a un lado. y dejarla como (3x2-2x+5) x Vale. 3x2-2x Si sacamos factor común. nos queda (3x-2)x . pero todavía lo podemos mejorar.. double resultado = 0. Nos queda 3x3-2x2+5x Rápidamente nos damos cuenta de que sobre esa expresión podemos sacar factor común. Bueno.multiplicaría x por sí mismo 15 veces. Así iríamos calculando la potencia de x a la vez que recorremos el vector de coeficientes. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //Este algoritmo es mucho mejor public double evaluar1(double x) { double pot = 1. Vamos a probar. //en cada iteración calculamos un monomio //y sumamos. En el primer algoritmo. con éste segundo algoritmo se realizan 30 multiplicaciones y 15 sumas. en cada iteración del bucle for se realizan sólo dos multiplicaciones y una suma. el -1. y luego la llamada a potencia(x. utilizaremos una variable que llamaremos pot para calcular las potencias de x. hemos disminuido muchísimo el número de operaciones.... y vamos a separar el coeficiente que no está multiplicado por x. por ejemplo de grado 15. } return resultado. Es necesario darse cuenta de que xn=x(n-1)x cuando n>1 y aprovecharlo..

...Ahora reescribamos todo junto. Haz las operaciones. el resultado al que hemos llegado y todo lo que nos hemos dejado a un lado: ((3x-2)x +5)x-1... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 //esta clase es sólo un ejemplo. Luego sumamos el siguiente y multiplicamos por x.. los errores de redondeo cometidos son mucho menores. resulta que sólo necesitamos una suma y una multiplicación por cada iteración del bucle. excepciones ni ninguna otra funcionalidad class Polinomio { //los coeficientes. pero escrito de otra forma. pues a esta forma de escribir los polinomios "((3x-2)x -5)x-1". Pues bien. Realmente. //una propiedad para obtener el grado //del polinomio int grado { get {return coeficientes. Luego sumamos el siguiente coeficiente y volvemos a multiplicar por x.. Bueno. y así sucesivamente. Le vamos a poner un constructor y una función evaluar que utilice el esquema de Horner. */ . empezamos por el coeficiente del monomio de mayor grado. Simplemente. y lo multiplicamos por x. pero ésto se logra gracias a la astuta parentización.. que representan a los coeficientes. ¿No me crees?.... cuando implementamos un algoritmo que se basa en evaluar un polinomio escrito según el esquema de Horner. tenemos el mismo polinomio de antes. al no realizarse operaciones de potencia.. para ilustrar //el algoritmo de Horner. de grado 0 a n double[] coeficientes. * El primero será el coeficiente del monomio de mayor * grado y el último el coeficiente del monomio de grado 0. De la expresion como suma de monomios hemos sacado la x como factor común unas cuantas veces. Vamos a poner todo juntito en una clase a la que llamaremos Polinomio. ((3x-2)x -5)x-1 = ((3x2-2x) -5)x-1 = (3x2-2x -5)x-1 = (3x3-2x2 +5x)-1 = 3x3-2x2 +5x-1 --> Nuestro polinomio como nuevo. se le denomina esquema de horner. y además.Length-1... en la cual. todas las veces que aparece x no está elevado a ninguna potencia.. No tiene control de //errores. x se va multiplicando por sí mismo.} } /* Este constructor admite una serie variable de * valores double. RecapitulandoPara evaluar un polinomio según el algoritmo de Horner. hasta que sumamos el último coeficiente y paramos..

-2. nos quedamos con el coeficiente del monomio de 28 //grado 0 en la posición 0 del vector. pasandole la lista de coeficientes. e invocar al método evaluar. y el coeficiente 29 //del monomio de grado n en la posición n. 46 } 47 //finalmente. 5. 44 //multiplicar el resultado por valor 45 resultado *= x. basta con crear un nuevo polinomio. sumamos el último coeficiente 48 return resultado+coeficientes[0].WriteLine(p. 31 } 32 33 //Evaluar mediante el algoritmo 34 //de Horner 35 public double evaluar(double x) 36 { 37 double resultado = 0.23 public Polinomio(params double[] coeficientes) 24 { 25 this. 38 //llegamos hasta el coeficiente 39 //del monomio de grado 1 40 for (int i = grado. i >= 1. i--) 41 { 42 //sumar un coeficiente 43 resultado += coeficientes[i].evaluar(7)).Reverse(this. 26 //vamos a darle la vuelta. sólo por comodidad 27 //así. 30 Array. .coeficientes = coeficientes. Por ejemplo: 1 2 3 4 //crear el polinomio Polinomio p = new Polinomio(3. -1). tal cual se escriben en el polinomio.coeficientes). 49 } 50 51 } //class Para utilizarlo. //evaluar para x=7 Console.