Está en la página 1de 39

Soluciones de una ecuacin de tercer grado en Excel.

Hace algn tiempo expliqu la manera de resolver, esto es, de encontrar la solucin de una ecuacin lineal de grado uno (ver); en aquel entonces utilic la herramienta Buscar objetivo. Recientemente, a travs de un comentario en el blog, un usuario peda ayuda para saber cmo solucionar una ecuacin de tercer grado:
...lo q necesito es encontrar mas de una raz, tengo un polinomio cubico y necesito las 3 races...

He de decir que para encontrar las tres races/soluciones de un polinomio cbico partir de una hiptesis de trabajo, que el polinomio tiene tres raices; sabemos que una ecuacin de tercer grado podra tener hasta tres puntos de corte con el eje X, es decir, hasta tres valores de X donde la ecuacin devuelve un valor igual a cero. Inicio el trabajo con un ejemplo de ecuacin de tercer grado con tres soluciones. y = 2x3 - 4x2 + 1 A pesar de mi hiptesis inicial, el mtodo de trabajo es vlido para cualquier polinomio cbico. El primer paso es escribir nuestra ecuacin de manera que Excel la entienda: =2*POTENCIA(A3;3)-4*POTENCIA(A3;2)+1 con esta frmula, en un segundo paso, construiremos una grfica (forma visual de encontrar las soluciones buscadas para nuestra ecuacin):

Ya en el grfico podemos ver cules son las races de la ecuacin, pero parece claro que depender mucho de los valores de la x que hayamos insertado para construir el grfico. Se hace necesario, por tanto, tener buena vista, o probar un par de veces, para conseguir el grfico adecuado a nuestros propsitos. Sin embargo, con el grfico slo podemos intuir la forma de la ecuacin y ms o menos por donde 'caen' las races. Para conocer las soluciones exactas nos basaremos en el grfico recin construido. Toca ahora construir un modelo sobre el que aplicar la herramienta SOLVER, que ser quien nos de nuestras races para la ecuacin.

Recuperaremos la frmula de la ecuacin: =2*POTENCIA(K2;3)-4*POTENCIA(K2;2)+1

Fijmonos que en la celda L5 aparece lo que ser la celda objetivo en el modelo de Solver; y que tambin he aadido lo que sern dos restricciones o condiciones en las celdas M3 y M4 que asegurarn que Solver no repita las races. Muy importante antes de ejecutar la herramienta Solver ser aprovechar el trabajo realizado al construir el grfico; y es que habr que 'ayudar' un poco a Solver a que nos devuelva las soluciones correctas. Viendo el grfico es fcil determinar que la primera raiz (la menor de todas) es negativa y que la segunda y tercera raz son positivas, obviamente la tercera mayor que la segunda. Realmente con esto sera suficiente, pero si lo estimamos necesario podemos ser ms precisos y decir que la primera raiz es un nmero cercano a -0,50, que la segunda es aproximdamente 0,60 y la tercera 1,90. Voy a trabajar de una manera general, sin llegar a ayudar a Solver con tanta precisin (probablemente muchas veces no pueda o quiera conocer esos valores). Escribo unos valores genricos que se adecen a lo comentado:

Cuanto ms prximos sean los valores dados ms rpido encontrar Solver las soluciones. Ya terminamos, ya que slo queda ejecutar Solver y definir sus restricciones. Desde el men Datos > Anlisis > Solver:

Y al resolver logramos por fin nuestras tres soluciones a la ecuacin...

Publicado por ExcelForo TEMAS: Buscar objetivo-Solver

http://excelforo.blogspot.com/2010/09/soluciones-de-una-ecuacion-de-tercer.html

RESOLUCIN DE ECUACIONES UTILIZANDO MICROSOFT EXCEL

1. Introduccin a Excel

Excel es un software diseado para su uso como hoja de clculo. Es decir, permite agilizar la realizacin de clculos de diversa ndole, siendo una herramienta muy extendida y potente. En este sencillo ejemplo vamos a explicar brevemente como es posible resolver una ecuacin cbica (que es la forma tpica de las ecuaciones de estado que vamos a usar en la asignatura) de una manera sencilla.

2. Ejemplo a resolver

La funcin de la que queremos obtener las races podra es: 4x3+3x2 6x2 = 0 Esta ecuacin tiene tres races reales, como puede observarse en la figura 1.

[pic] Figura 1. Representacin grfica de y=4x3+3x26x2

3. Resolucin en Excel

En Excel, a cada una las celdas (que estn formadas por la interseccin una fila y una columna) se le puede asignar un texto, un nmero o una operacin/funcin matemtica. La asignacin de texto o nmeros es directa, mientras que las operaciones van precedidas del signo =

[pic] Figura 2. Introduccin de datos en Excel

En la figura 2 se observa que se han asignado los coeficientes de la ecuacin cbica a resolver a las celdas B6, C6, D6 y E6. Para calcular el valor de la funcin (variable y), ser necesario especificar un valor de la variable x. Eso se ha hecho en la celda H8. El clculo del valor de y se ha realizado en la celda H6 escribiendo la secuencia que se ve la figura 2. Para escribir las celdas en las ecuaciones puede usar el teclado o bien usar el ratn para seleccionar la celda deseada. Nuestro objetivo es hacer que Excel cambie el valor de la variable x (al cual le hemos asignado un valor arbitrario) de modo que el valor de y sea cero. Para ello se utiliza la funcin buscar objetivo. Esta funcin se encuentra en DatosAnlisis y siBuscar objetivo, como puede observarse en la figura 3.

[pic] Figura 3. Ubicacin de la funcin buscar objetivo

El funcionamiento de buscar objetivo es sencillo. Una vez seleccionado, los parmetros a seleccionar son:

1) Definir la celda: se selecciona la celda en la que se quiere fijar le valor (es decir, nuestra variable y). Si se ha elegido las mismas celdas que en este tutorial, sera H6 2) Con el valor: se fija el valor (en nuestro caso 0) 3) Para cambiar la celda: se selecciona la celda que queremos que cambie de valor para llegar al objetivo (es decir, la variacin del valor de x). Segn la

figura 2 sera la celda H8

Una vez realizado esto, Excel iterar hasta buscar el objetivo.

4. Valor inicial de x

Como es bien conocido, la obtencin de una raz u otra de la ecuacin cbica depender de la seleccin de un valor inicial para la variable x. Es decir, depender del valor que ocupara la celda que contiene al valor de x (en este ejemplo la celda H8) antes de usar la funcin buscar objetivo.

Ejercicio: Calcule las tres races de la ecuacin y=4x3+3x26x2

Para la resolucin de ecuaciones cbicas de estado, los valores que interesan son los valores menor y mayor de x (que representaran, por ejemplo, el volumen parcial del lquido y del vapor, respectivamente). Las reglas explicadas en clase para la seleccin de valores iniciales en la resolucin iterativa a mano de ecuaciones cbicas tambin pueden ser aplicadas para la resolucin en Excel, garantizado que se calcula lo que realmente se est buscando
http://www.buenastareas.com/ensayos/Resoluci%C3%B3n-De-Ecuaciones-C%C3%BAbicasUsando-Excel/3660547.html

Conciliar una partida con Solver.


Vamos a ver cmo podemos encontrar, de un listado de valores, aquellos que suman una cantidad definida por nosotros; esto es, vamos a conciliar una partida con un listado de valores. Para esto emplearemos Solver. Si bien, hay que advertir que esta aplicacin ser vlida slo en aquellos casos que la combinacin de valores que suman el valor a conciliar (el valor buscado) es nica. Veamos nuestro listado de valores:

Convertiremos nuestro listado en una Tabla (Ctrl+q), y luego con la Tabla seleccionada,Insertaremos una columna de tabla a la derecha, que nombraremos como 'binario'. Tambin asignaremos nombre a los dos campos: binario =Hoja1!$B$2:$B$17 Cantidades =Hoja1!$A$2:$A$17 Por ltimo, como parte importante a la hora de configurar Solver, en la celda D2 insertaremos la funcin: =SUMAPRODUCTO(binario;Cantidades) esta funcin se encargar de multiplicar fila a fila, elemento a elemento, los valores del rango 'binario' y del rango 'Cantidades'. Esta celda, ser considerada en la configuracin como la Celda objetivo. Ejecutamos Solver, desde Datos > Anlisis > Solver:

Vemos que hemos seleccionado como celda objetivo la celda $D$2, donde se encontraba la funcin SUMAPRODUCTO. Adems, como Celdas cambiantes hemos seleccionado el rango binario; la consecuencia es que Solver completar este rango con los valores necesarios para que cumplan el objetivo y sus condiciones. El objetivo para nuestro ejemplo es encontrar aquella combinacin de cantidades que sumen 415,09. La nica condicin que damos es que cada uno de los valores del rango 'binario', tras la ejecucin de Solver nicamente podrn ser o ceros o unos (0 1), es decir, un nmero binario. Esto lo conseguimos agregando la siguiente condicin:

Ya estamos en disposicin de Resolver. Obteniendo la siguiente ventana de informacin:

El resultado es que ha encontrado la combinacin de valores del campo 'Cantidades' que suma 415,09: 415,09 = 126,35 + 71,00 + 117,75 + 99,99

Vemos como Solver ha aadido ceros y unos en el rango 'binario' hasta encontrar la combinacin por la que SUMAPRODUCTO(binario; Cantidades) = 415,09

Conciliar en Excel por aproximacin con Solver.


Tiempo atrs, expliqu en un post la manera de conciliar ciertos importes, empleando para ello la herramienta de Excel Solver (ver). Al hilo de este post un usuario preguntaba a travs de un comentario:
...podramos hacer que las posibilidades de suma fueran por un aproximado de por ejemplo 5 unidades arriba y 5 abajo?...

La respuesta a esta cuestin sera afirmativa, claro est bajo ciertos supuestos, ya que en caso de mltiples coincidencias solver siempre se decantara por una de las posibles soluciones. sin embargo construiremos un modelo en Excel que nos muestre en todo caso, de todas las aproximaciones posibles a buscar, la que sea ms prxima al valor buscado. Importante aclarar, buscamos por aproximacin al total de la suma. Veamos nuestros datos de partida:

Realmente, nuestra base de trabajo es similar a la expuesta en la entrada Conciliar una partida con Solver, si bien, necesitaremos ciertas modificaciones. En primer lugar, construiremos dos columnas C y D anexas, ambas con la misma frmula =A2*B2 para luego acabar sumando estos valores en C8 y D8 =SUMA(C2:C7) y =SUMA(D2:D7); sumas que emplearemos despus al Agregar nuestras condiciones de Solver. Importante tambin es definir correctamente la que ser celda objetivo E8, con la frmula: =ABS(((G2*2)-(D8+C8))/2) sabiendo que nuestro modelo es el siguiente, con la disposicin de celdas que vemos en la imagen:

Adems de la formulacin de la celda $E$8 (futura celda objetivo), es clave determinar cul es el factor de aproximacin, en mi ejemplo ser de 2 por encima o por debajo del valor buscado o a

conciliar (27,92); estos valores sern empleados al construir las condiciones de Solver. Ejecutemos la herramienta Solver, as que iremos a la Ficha Datos > Anlisis > Solver, y configuraremos los diferentes parmetros:

haz click en la imagen

Observemos como hemos seleccionado minimizar el valor de la celda objetivo $E$8, cambiando el rango de celdas $B$2:$B$7, es decir, las celdas de nuestra Tabla origen, por las que multiplicaremos cada importe. Y en cuanto a las tres restricciones, forzamos a que el rango $B$2:$B$7 sean 1 0 (resultado binario), adems de restringir que la suma del producto de cada registro por ese valor binario a obtener sea mayor o igual que el mnimo (valor buscado menos la aproximacin) y menor o igual que el mximo (valor buscado ms la aproximacin). Con estas restricciones, al minimizar el modelo desarrollado, conseguiremos llegar a las partidas que mejor se aproximan al valor buscado, esto es a la 'conciliacin por aproximacin'. Si Aceptamos la configuracin, vemos la respuesta dada:

Que al comprobar manualmente con las diferentes combinaciones que se acercan al resultado buscado, podemos ver que ciertamente el resultado propuesto es, de todos los posibles, el ms prximo.

kaz click en la imagen

Para nuestro ejemplo, las partidas cuya suma se aproximan ms a 27,92 son 10,00 + 15,00 + 2,90. Por supuesto, este mtodo, sera vlido tambin para la conciliacin exacta. Publicado por ExcelForo

http://www.ayudaexcel.com/foro/macros-programacion-vba-10/ecuacion-excel-17856/
Hola, una forma manual de hacerlo a grandes rasgos sera: a) generas 3 celdas con nombre, es decir, X, N y M b) generas la formula como en la imagen c) activas el cuadro de dialogo "Buscar objetivo" y lo estableces como en la imagen anexa.

Races de un polinomio. Mtodo de Graeffe


http://www.sc.ehu.es/sbweb/fisica_/numerico/raices/graeffe.xhtml

En esta pgina, se describe un procedimiento matemtico ingenioso para hallar las races de un polinomio con gran exactitud. El mtodo de Graeffe se presta especialmente a ser programado en el ordenador, constituyendo de por s un ejercicio relevante, en lo que concierne a los aspectos generales del lenguaje Java: sentencias condicionales e iterativas, arrays unidimensionales y bidimensionales, descomposicin de un problema en tareas que se codifican en forma de funciones, y finalmente, la encapsulacin de los datos y las funciones para formar una clase. En muchos campos de las matemticas es necesario hallar las races de un polinomio, por ejemplo, para calcular la integral de una funcin racional, para calcular las races del polinomio caracterstico que son los valores propios de una matriz, etc. Solamente existen frmulas si el polinomio tiene un grado igual o inferior a cuatro. Excepto para los polinomios de primer y segundo grado, las frmulas son complicadas, por lo que se emplean procesos de aproximacin numrica. Entre los numerosos mtodos que existen, el ms conocido es quiz el mtodo de Newton. Sin embargo, describiremos un mtodo, realmente ingenioso, que nos proporciona gran exactitud en las races de un polinomio. Sea el polinomio a 0 x n + a 1 x n1 + a 2 x n2 + a 3 x n3 + ... a n1 x+ a n =0 (1)

Hacemos el polinomio ms simple dividiendo todos los coeficientes por el primer trmino de modo que a0 es siempre 1. Supongamos que sus races reales y distintas son -r1, -r2, -r3, ...-rn Al elevar al cuadrado el polinomio y agrupar los trminos se obtiene un polinomio de grado 2n a 0 2 ( x n ) 2 ( a 1 2 2 a 2 a 0 ) ( x n1 ) 2 +( a 2 2 2 a 1 a 3 +2 a 4 a 0 ) ( x n2 ) 2 ( a 3 2 2 a 2 a 4 +2 a 1 a5 2 a 6 a 0 ) ( x n3 ) 2 + ...=0 } (2) Cuyas races sern r 1 2 , r 2 2 , r 3 2 ... r n 2 Hemos construido as una nueva ecuacin cuyas races son numricamente iguales a los cuadrados de las races de la ecuacin original. Repitiendo el proceso, se pueden obtener ecuaciones cuyas races sean numricamente

iguales a las potencias cuarta, octava, decimosexta, etc. de las races de la ecuacin original. El efecto de este proceso de elevar al cuadrado es el de producir ecuaciones cuyas races estn cada vez ms separadas. Por ejemplo, si dos races de la ecuacin original estn entre s como 5 : 4 sus potencias 128 estn en la razn 5128 : 4128, o sea, 2.54 1012: 1, lo que es muy deseable ya que las ecuaciones cuyas races estn muy separadas se pueden resolver rpidamente con exactitud considerable. Supngase ahora, que reiterando el proceso de elevacin al cuadrado se llega a un polinomio 0 ( x n ) 2 m + 1 ( x n1 ) 2 m + 2 ( x n2 ) 2 m + 3 ( x n3 ) 2 m + ... =0 (3) donde m es el nmero de veces que se repite el proceso de elevacin al cuadrado. As, si se repite siete veces el proceso de elevacin al cuadrado, 2m =27 =128 sera el exponente al que estaran elevados las sucesivas potencias xn, xn-1, xn-2, ... del polinomio. Sus races sern las del polinomio original elevadas al exponente 2m. r 1 2 m , r 2 2 m , r 3 2 m , ... r n 2 m Por las relaciones conocidas entre races y coeficientes del polinomio, se tiene que 0 =1 1 =(suma de las races)= r 1 2 m + r 2 2 m + ... + r n 2 m 2 =(suma de las races tomando dos cada vez)= r1 2 m r 2 2 m + r 1 2 m r 3 2 m + ... + r 2 2 m r 3 2 m + ... + r n1 2 m r n 2 m 3=(suma de las races tomando tres cada vez)= r 1 2 m r 2 2 m r 3 2 m + r 1 2 m r 2 2 m r 4 2 m + ... + r 2 2 m r 3 2 mr 4 2 m + .. . + r n2 2 m r n1 2 m r n 2 m n = ( 1 ) n (producto de todas las races)= r 1 2 m r 2 2 m r 3 2 m ... r n2 m En la suposicin de que | r 1 |>| r 2 |>| r 3 |> ... | r n | y de que 2m es grande por ejemplo 128 256, se cumplir que | r 1 | 2 m >>> | r 2 | 2 m >>> | r 3 | 2 m >>> ... | r n | 2 m donde el smbolo >>> indica mucho mayor que. Las relaciones entre coeficientes y races quedarn simplificadas con gran aproximacin a las expresiones. 0 =1 1 = r 1 2 m 2 = r 1 2 m r 2 2 m 3 = r 1 2 m r 2 2 m r 3 2 m n = r 1 2 m r 2 2 m r 3 2 m ... r n 2 m

As, el mdulo de r1 se puede hallar extrayendo la raz 2m-sima de 1 . De la segunda ecuacin se obtiene r2, y as sucesivamente. La frmula para obtener el mdulo de la raz ri es | r i |= i i1 2 m En la prctica, hallamos el logaritmo de ri, y luego, calculamos el antilogaritmo del resultado obtenido, de este modo se obtiene el valor absoluto de la raz ri. log| r i |= log i log i1 2 m (4) Para determinar el signo, se halla el valor del polinomio original para los valores ri, y -ri, uno de los dos har que dicho valor sea prximo a cero y por tanto, ser la raz buscada.
Clculo de los coeficientes en las sucesivas iteracciones

Un polinomio cuyas races son reales y distintas es el caso ms simple que se nos puede presentar. Sea por ejemplo el polinomio x3-4x2+x+6,cuyas races como se puede comprobar fcilmente por simple sustitucin son 3, 2, y -1. En la tabla se observa los coeficientes i resultantes del proceso de elevacin del polinomio a las potencias 2, 4, 8, 16, 32, 64, 128, 256 y 512 respectivamente.

El primer coeficiente 0 es uno El segundo 1 se obtiene a partir de los coeficientes de la fila anterior mediante la expresin a 1 2 2 a 2 a 0 El tercer coeficiente 2 mediante la expresin a 2 2 2 a 1 a 3 El cuarto coeficiente 3 mediante la expresin a 3 2 0 1.0 1.0 1.0 1.0 1.0 1 -4.0 14.0 98.0 6818.0 4.3112 107 2 1.0 49.0 1393.0 1.6864 106 2.8212 1012 3 6.0 36.0 1296.0 1.6796 106 2.8211 1012

m (2m) 0 (1) 1 (2) 2 (4) 3 (8) 4 (16)

5 (32) 6 (64) 7 (128) 8 (256) 9 (512)

1.0 1.0 1.0 1.0 1.0

1.8553 1015 3.4337 1030 1.179 1061 1.3901 10122 1.9323 10244

7.9587 1024 6.334 1049 4.012 1099 1.6096 10199 2.5908 10398

7.9587 1024 6.334 1049 4.012 1099 1.6096 10199 2.5908 10398

Podemos observar en la tabla que cada coeficiente en la iteracin 9, es aproximadamente el cuadrado del coeficiente en la iteracin precedente, habindose eliminado el efecto de los dobles productos A partir de este ejemplo, tenemos que codificar el procedimiento de Graeffe cualquiera que sea el grado n del polinomio y el nmero m de veces que se repite el proceso de elevacin al cuadrado, lo que requiere los siguientes pasos: 1. Crear en memoria un array bidimensional de MAX_ITER filas y n+1 columnas (n es el grado del polinomio), para guardar los coeficientes del polinomio, tras la aplicacin sucesiva del procedimiento de elevacin al cuadrado, tal como se ve en la tabla. 2. Obtener los coeficientes de la siguiente fila a partir de la fila anterior, mediante las expresiones (2) 3. Obtener las races del polinomio, primero, su valor absoluto mediante la frmula (4) y luego su signo, y guardarlas en un array unidimensional de dimensin n. 4. Mostrar las races del polinomio. Reservamos memoria para un array bidimensional a, y guardamos en la primera fila los coeficientes del polinomio, de mayor a menor grado.
a= new double[MAX_ITER][n+1]; //la primera fila de la tabla guarda los coeficientes del polinomio for(int j=0; j<n+1; j++){ a[0][j]=coef[j]; } for(int m=1; m<MAX_ITER; m++){ for(int j=0; j<n+1; j++){ a[m][j]=0.0; } }

Donde MAX_ITER es el nmero mximo de iteracciones, o de veces que se repite el proceso de elevacin al cuadrado. En una funcin miembro denominada tabla, codificaremos el procedimiento de elevacin al cuadrado de un polinomio de grado n. Partiendo del polinomio original (1), obtenemos el polinomio resultante del procedimiento de elevar al cuadrado (3) segn el esquema (2). En la expresin (2) observamos que el coeficiente de grado i del nuevo polinomio i se obtiene efectuando las siguientes operaciones entre los coeficientes del polinomio original: se calcula el cuadrado de ai y se halla el doble producto de los elementos equidistantes ak y al, siendo los ndices k=i-s y l=i+s, con s=1, 2, 3... hasta que se llegue al final del polinomio. Por ejemplo, los elementos equidistantes a a3 en un polinomio de 6 grado son (a2, a4), (a1, a5) y (a0, a6). Por tanto, el nuevo coeficiente i del polinomio elevado al cuadrado se calcular mediante la frmula 3 = a 3 2 2 a 2 a 4 +2 a 1 a 5 2 a 0 a 6 Sorprendentemente, el lenguaje Java, no produce error por "overflow", es decir, cuando se supera el lmite mximo o mnimo para un tipo de dato bsico: int, long, o double. Por ejemplo, podemos guardar nmeros enteros en una variable tipo int siempre que est en el intervalo -2147483648 a 2147483647. Las clases que envuelven a los tipos primitivos de datos, Integer, Double, etc. nos proporcionan funciones miembro que nos notifican cuando se sobrepasen los lmites especificados para un tipo de dato dado. En el cdigo de la funcin tabla, cuando se supera el valor mximo que puede guardar un dato de tipo double, se interrumpe el proceso de elevacin al cuadrado, y se sale fuera del bucle. La funcin esttica isInfinite de la claseDouble se encarga de verificarlo devolviendo true si hemos superado dicho lmite permitido.
exterior: do{ for(int i=0; i<n+1; i++){ a[m][i]=a[m-1][i]*a[m-1][i]; if(Double.isInfinite(a[m][i])){ break exterior; } } //.... m++; }while(m<MAX_ITER);

Es necesario emplear un break con una etiqueta para salir al bucle exterior do...while, e interumpir el proceso de elevacin al cuadrado. Si

solamente empleamos break salimos del bucle interior for y se continuara en el bucledo...while el proceso de clculo. Nos queda ahora, la determinacin el signo de cada uno de los dobles productos. Si el ndice s es impar, entonces el signo es negativo y si es par, el signo es positivo. En vez de elevar -1 a la potencia s, empleamos el operador mdulo %en conjuncin con la macro if ... else, que se leer: si s es impar (el resto de dividir s entre 2 es cero), entonces el valor de la variable entera signo es +1 en caso contrario es -1.
signo=(s%2==0)? +1: -1;

Los coeficientes del polinomio original se guarda en el array a[0][i], (i=0 ... n). Cuando se eleva al cuadrado los coeficientes del nuevo polinomio se guardan en el array a[1][i], (i=0 ... n), y as sucesivamente. Los coeficientes a[m][i], (i=0 ... n) corresponden al polinomio que se ha elevado a la potencia 2m. Dicha potencia se calcula mediante un buclefor.
pot2=1; for(int i=1; i<=m; i++){ pot2*=2; }

El cdigo de la funcin tabla, que calcula los coeficientes polinomio resultante del proceso de elevar el polinomio original sucesivamente al cuadrado m veces, es el siguiente
private void tabla(){ int k,l, signo; //divide el polinomio por el primer coeficiente, las races no cambian for(int i=1; i<n+1; i++){ a[0][i]/=a[0][0]; } a[0][0]=1.0; m=1; exterior: //etiqueta do{ //cuadrados for(int i=0; i<n+1; i++){ a[m][i]=a[m-1][i]*a[m-1][i]; if(Double.isInfinite(a[m][i])){ break exterior; } } //dobles productos for(int i=1; i<n; i++){ for(int s=1; s<n/2+1; s++){ k=i-s; l=i+s; if((k<0)||(l>n)) break; //trminos simtricos signo=(s%2==0)? +1: -1; a[m][i]+=signo*2*a[m-1][k]*a[m-1][l]; if(Double.isInfinite(a[m][i])){

break exterior; } } } m++; }while(m<MAX_ITER); m--; //potencia de m de 2 pot2=1; for(int i=1; i<=m; i++){ pot2*=2; } }

Races reales y distintas

Un polinomio cuyas races son reales y distintas es el caso ms simple que se nos puede presentar. Volvemos a estudiar el polinomio x3-4x2+x+6, cuyas races como se puede comprobar fcilmente por simple sustitucin son 3, 2, y -1. En latabla que creamos en el apartado anterior, nos fijamos en la ltima fila. m (2m) 0 (1) 9 (512) 0 1.0 1.0 1 -4.0 1.9323 10244 2 1.0 2.5908 10398 3 6.0 2.5908 10398

Los mdulos de las races reales, se calculan mediante la frmula (4). Para hallar las races con gran exactitud tomaremos los coeficientes que figuran en la ltima fila, resultado de elevar el polinomio a la potencia 512. log r0=(log(1)-log(0))/2m log r0=(log(1.9323 10244)-log(1))/512 r0 sale 3 log r1=(log(2)-log(1))/2m log r1=(log(2.5908 10398)-log(1.9323 10244))/512 r1 sale 2 log r2=(log(3)-log(2))/2m log r2=(log(2.5908 10398)-log(2.5908 10398))/512 r2 sale 1

Para codificar estos clculos, emplearemos las funciones Math.log que halla el logaritmo de la raz, y la funcin recprocaMath.exp, para hallar la raz. El valor absoluto de la raz real se guarda en la variable local raiz.
private void raizRealSimple(int j){ //valor absoluto de la raz double logaritmo=(Math.log(a[m][j])-Math.log(a[m][j-1]))/pot2; double raiz=Math.exp(logaritmo); //determinacin del signo raicesReales[numReales]=(Math.abs(valorPolinomio(raiz)) <Math.abs(valorPolinomio(-raiz)))? raiz : -raiz; numReales++; }

Para determinar el signo de la raz real, hallaremos el valor del polinomio para dos valores raiz y -raiz, uno de los dos tiene que ser cero o muy prximo a cero. Una vez hallada la raz real, su valor absoluto y su signo, se guarda en el arrayraicesReales.
Races reales dobles

En el apartado anterior, hemos supuesto que las races de un polinomio son reales y distintas, por lo que la aplicacin del mtodo de Graeffe es inmediata. Supongamos el polinomio x3-7x2+16x-12 que tiene una raz doble 2, y una simple 3. Examinemos el comportamiento de sus coeficientes en el proceso de elevacin al cuadrado en la tabla. Observaremos que el segundo coeficiente 1 se comporta como hemos descrito en el apartado anterior, cada coeficiente en una iteracin es aproximadamente el cuadrado de la iteracin precedente. Sin embargo, este comportamiento no se produce en el tercer coeficiente 2, ya que se obtiene la mitad del valor esperado. Por ejemplo, el valor de 2 en la sptima iteracin es 8.024 1099 y su cuadrado es 6.4384 10199, sin embargo, se obtiene la mitad 3.2192 10199. Lo mismo ocurre en octava iteracin el cuadrado de 3.2192 10199 es 1.0363 10399, sin embargo, obtenemos la mitad de este valor 5.1817 10398. Al tercer coeficiente, 2(ndice 2), se denomina excepcional, y seala la presencia de races reales dobles. m (2m) 0 (1) 1 (2) 2 (4) 0 1.0 1.0 1.0 1 -7.0 17.0 113.0 2 16.0 88.0 2048.0 3 -12.0 144.0 20736.0

3 (8) 4 (16) 5 (32) 6 (64) 7 (128) 8 (256) 9 (512)

1.0 1.0 1.0 1.0 1.0 1.0 1.0

7073.0 4.3178 107 1.853 1015 3.4337 1030 1.179 1061 1.3901 10122 1.9323 10244

3.4248 106 5.6465 1012 1.5917 1025 1.2668 1050 8.024 1099 3.2192 10199 5.1817 10398

4.2998 108 1.8488 1017 3.4182 1034 1.1684 1069 1.3652 10138 1.8638 10276 3.4737 10552

Para obtener la raz doble, se ha de aplicar la siguiente frmula que damos sin justificar. La raz repetida se puede hallar calculando la raz 22m de la razn de los coeficientes que inmediatamente preceden y siguen al coeficiente excepcional. Si i es el coeficiente excepcional, el mdulo de la raz doble se calcula mediante la frmula | r i |= 2 m+1 i+1 i1 (5)

La codificacin de la funcin raizRealDoble es similar a la funcin raizRealSimple. Primero, halla el mdulo de la raz aplicando la frmula (5), y posteriormente, determina su signo. La raz buscada se guarda dos veces en el arrayraicesReales, y se incrementa dos unidades el contador de races reales numReales.
private void raizRealDoble(int j){ //valor absoluto de la raz double logaritmo=(Math.log(a[m][j+1])-Math.log(a[m][j-1]))/(2*pot2); double raiz=Math.exp(logaritmo); //determinacin del signo boolean bPositiva=false, bNegativa=false; if (Math.abs(valorPolinomio(raiz))<CERO){ raicesReales[numReales]=raiz; numReales++; bPositiva=true; } if (Math.abs(valorPolinomio(-raiz))<CERO){ raicesReales[numReales]=-raiz; numReales++; bNegativa=true; } if(bPositiva && !bNegativa){ raicesReales[numReales]=raiz;

numReales++; } if(!bPositiva && bNegativa){ raicesReales[numReales]=-raiz; numReales++; } }

Una raz compleja y su conjugada

Los polinomios pueden tener tambin races complejas y sus respectivas conjugadas. El caso ms simple es el del un polinomio x2+1 que tiene una raz compleja y su correspondiente conjugada. Sea el polinomio x3-7x2+16x-12 que tiene las siguientes races exactas: 3, 2-3i, 2+3i. Examinando en la tabla los valores y los signos de los coeficientes en las sucesivas iteraciones, vemos que el segundo coeficiente 1 cambia de signo en la tercera iteracin, adems el valor del coeficiente en una iteracin no es aproximadamente igual al cuadrado de su valor en la siguiente iteracin, sino la mitad de dicho valor, un comportamiento similar al de las races dobles. Al coeficiente 1 le denominaremos coeficiente excepcional. m (2m) 0 (1) 1 (2) 2 (4) 3 (8) 4 (16) 5 (32) 6 (64) 7 (128) 8 (256) 0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1 -7.0 -1.0 -157.0 6083.0 -1.5882 109 1.3319 1018 8.8358 1035 3.886 1071 7.4134 10142 2 25.0 79.0 9283.0 8.1259 108 5.952 1017 4.4524 1035 1.9606 1071 3.8437 10142 1.4774 10285 3 -39.0 1521.0 2.3134 106 5.352 1012 2.8644 1025 8.2048 1050 6.7319 10101 4.5318 10203 2.0537 10407

9 (512)

1.0

2.5411 10285

2.1827 10570

4.2177 10814

Para conocer si un polinomio tiene races complejas y sus correspondientes conjugadas basta examinar el cambio de signo de los coeficientes en sucesivas iteraciones, a partir, por ejemplo, de la segunda. Para ello, declaramos y definimos una funcin miembro denominada cambiaSigno que explora cada columna buscando cambios de signo en el coeficiente de orden j, tras sucesivas iteraciones. Si no detecta ningn cambio de signo devuelve false y si encuentra un cambio de signo, quiere decir, que ha encontrado una raz compleja y su correspondiente conjugada, aadindose una unidad al contador numComplejas. Posteriormente, calcula el mdulo de dicha raz, y por ltimo, devuelve true.
private boolean cambiaSigno(int j){ for(int k=2; k<=m; k++){ if(a[k][j]>0) continue; //..... return true; } return false; }

El mdulo de las races complejas se determina mediante la misma frmula que las races dobles., calculando la raz 22mde la razn de los coeficientes que inmediatamente preceden y siguen al coeficiente excepcional. Para calcular una raz compleja hemos de determinar su parte real, ya que la parte imaginaria se obtiene a partir de su mdulo y de su parte real. Denotemos las races complejas como u+vi y u-vi, si conocemos la parte real u, la parte imaginaria v se determina mediante la frmula v= r 2 u 2 , donde r es el mdulo obtenido a partir de la frmula (5). Queda, por tanto, determinar la parte real u, mediante la frmula que daremos sin justificar. u= 1 2 ( coeficiente de x n-1 +suma de todas las races reales ) El cdigo de la funcin denominada unaRaizCompleja, calcula primero la suma de todas las races reales. Luego, se determina u, y a partir de u se calcula v. La raz compleja y su correspondiente conjugada se guardan el arrayraicesComplejas.
private void unaRaizCompleja(){ double suma=0.0; for(int i=0; i<numReales; i++){ suma+=raicesReales[i]; } double u, v; u=-(a[0][1]+suma)/2;

v=Math.sqrt(moduloComplejas[0]*moduloComplejas[0]-u*u); raicesComplejas[0]=new Complejo(u, v); raicesComplejas[1]=new Complejo(u, -v); }

En esta porcin de cdigo, hemos empleado un nuevo tipo de dato, denominado Complejo. Se trata de una clase cuyos miembros dato son la parte real y la parte imaginaria del nmero complejo y como funciones miembro, tiene los constructores, las funciones que suman, restan, multiplican o dividen dos numeros complejos.
Dos races complejas y sus conjugadas

Supongamos ahora el polinomio x5-4x4+11x3+4x2-10x-52 que tiene una raz real 2 y dos races complejas y sus correspondientes conjugadas, 2+3i, 2-3i, 1+i, -1-i. Examinando la tabla vemos que los coeficientes segundo 1 y quinto 4 cambian de signo y adems, se comportan de modo similar al de las races dobles, signo inequvoco de una raz compleja. Por tanto, el polinomio tendr dos races complejas y sus respectivas conjugadas, en total cuatro races que es el mximo nmero que permite este procedimiento. m (2m) 0 1 0 (1) 1 (2) 2 (4) 3 (8) 4 (16) 5 (32) 6 (64) 1.0 -4.0 1.0 -6.0 1.0 -230.0 1.0 -190.0 1.0 -1.6312 109 1.0 1.3301 1018 1.0 8.8357 1035 2 11.0 133.0 2.6545 104 8.156 108 6.6531 1017 4.4278 1035 1.9605 1071 3.8437 10142 1.4774 10275 3 4.0 652.0 2.554 105 2.3493 1011 4.3949 1022 1.9018 1045 3.6165 1090 1.3079 10181 1.7107 10362 4 -10-0 516.0 -3.2598 106 6.8913 1012 2.2371 1025 2.4926 1050 3.1066 10100 4.8255 10200 1.1643 10401 5 -52.0 2704.0 7.3116 106 5.346 1013 2.8579 1027 8.1678 1054 6.6714 10109 4.4507 10219 1.9809 10439

7 (128) 1.0 3.886 1061 8 (256) 1.0 7.4134 10142

9 (512) 1.0 2.5411 10285

2.1827 10570

2.9265 10724

6.7774 10801

3.9238 10878

Denotaremos las dos races complejas y sus respectivas conjugadas como u1v1i y u2v2i. Conocidos u1 y u2 se calculav1 y v2 mediante las frmulas v1=r12u12 v2=r22u22 Para determinar u1 y u2 se emplean las siguientes frmulas u 1 + u 2 = 1 2 ( coeficiente de x n1 +suma de todas las races reales ) u 1 r 2 2 + u 2 r 1 2 = (1) n1 a n1 2(pro ducto de las n-4 races reales ) r 1 2 r 2 2 2 ( suma de las inversas de las n4 races reales ) Se trata de un sistema de dos ecuaciones con dos incgnitas de las que se despeja u1 y u2 La funcin denominada dosRaicesComplejas, calcula la suma de todas las races reales, el producto y la suma de las inversas de dichas races. Despus calcula los segundos miembros de cada una de las dos ecuaciones y los guarda en las variables locales y y z La solucin del sistema de dos ecuaciones con dos incgnitas es u 1 = y r 1 2 z r 1 2 r 2 2 u 2 = y r 2 2 +z r 1 2 r 2 2 lo que nos permite calcular u1 y u2y posteriormente, v1 y v2 Finalmente, guardamos los valores obtenidos en el array raicesComplejas
private void dosRaicesComplejas(){ double suma=0.0; double producto=1.0; double inversa=0.0; for(int i=0; i<numReales; i++){ suma+=raicesReales[i]; producto*=raicesReales[i]; inversa+=1/raicesReales[i]; } double r1=moduloComplejas[0]; double r2=moduloComplejas[1]; double y=-(a[0][1]+suma)/2; int signo=((n-1)%2==0)? +1: -1; double z=signo*a[0][n-1]/(2*producto)-r1*r1*r2*r2*inversa/2; double double double double u1=(y*r1*r1-z)/(r1*r1-r2*r2); u2=(-y*r2*r2+z)/(r1*r1-r2*r2); v1=Math.sqrt(r1*r1-u1*u1); v2=Math.sqrt(r2*r2-u2*u2);

raicesComplejas[0]=new raicesComplejas[1]=new raicesComplejas[2]=new raicesComplejas[3]=new }

Complejo(u1, Complejo(u1, Complejo(u2, Complejo(u2,

v1); -v1); v2); -v2);

La funcin discriminadora

La funcin pblica hallaRaices se encarga de llamar a la funcin tabla para calcular los coeficientes polinomio resultante del proceso de elevar el polinomio original sucesivamente al cuadrado. Los coeficientes se guardan en el array bidimensional a[m][i] (i=0... n) donde m representa la iteracin, e i el coeficiente: 0 es el ndice del coeficiente de mayor grado y n es el ndice del trmino independiente.
private boolean cambiaSigno(int j){ double logaritmo; for(int k=2; k<=m; k++){ if(a[k][j]>0) continue; numComplejas++; //mximo dos races complejas, 4 contando sus respectivas conjugadas if(numComplejas<3){ logaritmo=(Math.log(a[m][j+1])-Math.log(a[m][j-1]))/(2*pot2); moduloComplejas[numComplejas-1]=Math.exp(logaritmo); return true; } } return false; }

Ya que a[m][0] es siempre la unidad analizaremos cada uno de los n coeficientes restantes a[m][i] (i=1 ... n). En primer lugar, miraremos si hay cambios de signo en cada uno de los coeficientes i, llamando a la funcin cambiaSigno, y pasndole el ndice i. Si la funcin devuelve true, quiere decir que se ha detectado una raz compleja y su correspondiente conjugada.
tabla(); //el pimer coeficiente a[m][0] es siempre 1 for(int i=1; i<n+1; i++){ //i es la raz if(cambiaSigno(i)){ //raz compleja y su correspondiente conjugada i++; continue; }

Posteriormente, analiza si hay una raz doble, comprobando la relacin entre los valores del coeficiente i en las dos ltimas iteraciones. Recurdese que a[m][i] es habitualmente el cuadrado de a[m-1][i], salvo para los

coeficientes excepcionales. Cuando hay presentes races dobles a[m][i] es el cuadrado de a[m-1][i] dividido entre dos. La variable local cociente valdr habitualmente cero, salvo en el caso de races dobles. Cuando la variable cociente de la funcincambiaSigno es cero (el logaritmo de la unidad es cero) o un valor muy prximo a cero (menor que la constante CEROfijada de antemano), se llama a la funcin raizRealSimple para hallar la raz correspondiente al coeficiente i del polinomio. En caso contrario, tendremos una raz doble y se llamar a la funcin raizRealDoble para calcularla.
//races simple y dobles double logaritmo=Math.log(a[m][i])-2*Math.log(a[m-1][i]); if(Math.abs(logaritmo)<CERO){ raizRealSimple(i); }else{ raizRealDoble(i); i++; continue; } }

La primera verificacin se realiza sobre las races complejas ya que cumplen una condicin ms estricta que las races dobles, es decir, se comportan como las races dobles pero adems presentan cambios de signo en las primeras iteraciones, mientras el trmino cuadrado no domina sobre los dobles productos. Una vez concluido el anlisis de cada uno de los coeficientes del polinomio en las sucesivas iteraciones que lo elevan al cuadrado y se han calculado las races reales simples y dobles se procede al clculo de las races complejas. Si solamente hay una raz compleja y su conjugada, se llama a la funcin unaRaizCompleja.
if(numComplejas==1){ unaRaizCompleja(); }

Si hay dos races complejas y sus conjugadas, se llama a la funcin dosRaicesComplejas.


if(numComplejas==2){ dosRaicesComplejas(); }

El cdigo completo de la funcin miembro hallarRaices que calcula todas las races de un polinomio se muestra a continuacin
public void hallarRaices(){ tabla(); //el pimer coeficiente a[m][0] es siempre 1 for(int i=1; i<n+1; i++){ if(cambiaSigno(i)){

//raz compleja y su correspondiente conjugada i++; continue; } //races simple y dobles double logaritmo=Math.log(a[m][i])-2*Math.log(a[m-1][i]); if(Math.abs(logaritmo)<CERO){ raizRealSimple(i); }else{ raizRealDoble(i); i++; continue; } } if(numComplejas==1){ unaRaizCompleja(); } if(numComplejas==2){ dosRaicesComplejas(); } }

Mostrar las races calculadas

Primero, se muestran las races reales con dos cifras decimales


(double)Math.round(raicesReales[i]*100)/100

A continuacin, se muestran las races complejas


System.out.println(raicesComplejas[2*i]);

La funcin println no solamente imprime objetos de la clase String, sino que tambin imprime datos numricos de los tipos bsicos y como vemos convierte automticamente un nmero complejo en su representacin textual, pero para ello hemos de redefinir en dicha clase la funcin toString miembro de la clase base Object de la cual derivan todas las clases en Java. La llamada implcita a dicha funcin muestra la parte real seguida de la imaginaria ambas con dos cifras decimales y seguida de la unidad imaginaria i. El cdigo completo de la funcin mostrarRaices es el siguiente.
public void mostrarRaices(){ hallarRaices(); //races reales System.out.println("Races reales"); for(int i=0; i<numReales; i++){ System.out.println((double)Math.round(raicesReales[i]*100)/100+" ---> "+ valorPolinomio(raicesReales[i])); } System.out.println(""); //races complejas System.out.println("Races complejas"); for(int i=0; i<numComplejas; i++){

System.out.println(raicesComplejas[2*i]+" ---> "+ valorPolinomio(raicesComplejas[2*i])); System.out.println(raicesComplejas[2*i+1]+" ---> "+ valorPolinomio(raicesComplejas[2*i])); } System.out.println(""); }

Comprobacin de las races

La funcin valorPolinomio halla el valor de un polinomio para un valor real de su variable x. Dicha funcin calcula primero las sucesivas potencias de x, las guarda en el array pot_x, y luego, las multiplica por sus respectivos coeficientes y suma los resultados.
public double valorPolinomio(double x){ double y=0.0; //sucesivas potencias de x, se puede utilizar tambien la funcion Math.pow double[] pot_x=new double[n+1]; pot_x[0]=1.0; for(int i=1; i<n+1; i++){ pot_x[i]=pot_x[i-1]*x; } //valores de los sucesivos trminos for(int i=0; i<n+1; i++){ y+=a[0][i]*pot_x[n-i]; } return y; }

Es algo ms complicado hallar el valor del polinomio cuando la variable es compleja x. Tendremos que hallar las sucesivas potencias de la variable compleja, multiplicar por los coeficientes y sumar los resultados. La clase Complejoque describe dicha entidad matemtica ha definir las siguientes operaciones: la suma de dos nmeros complejos, el producto de un nmero real por un nmero complejo y la potencia de un nmero complejo. La funcin valorPolinomio devolver un nmero complejo, cuando se le pasa en su nico argumento otro nmero complejo. Su definicin en trminos de las funciones mencionados es la siguiente.
public Complejo valorPolinomio(Complejo x){ Complejo y=new Complejo(); for(int i=0; i<n+1; i++){ y=Complejo.suma(y, Complejo.producto(a[0][i], Complejo.potencia(x, (ni)))); } return y; }

Ejemplos

Para hallar las races de un polinomio, primero creamos un array de los coeficientes, de mayor a menor grado. Para el polinomio x3-4x2+x+6 se escribir
double[] coef={1, -4, 1, 6};

A continuacin, se crea un objeto g de la clase Graeffe y le pasamos el array de los coeficientes coef a su constructor. Desde dicho objeto se llama a la funcin miembro mostrarRaices, para hallar y mostrar las races del polinomio.
Graeffe g=new Graeffe(coef); g.mostrarRaices();

Para que practique el lector, se le propone hallar las races de los siguientes ecuaciones polinmicas: x3-0x2-3x+1=0 x4+x3-10x2-34x-26=0 x4+0x3+4x2-3x+3=0 x3-6x2+11x-7=0 x3+2x2+2x+2=0 x4-x3-10x2-x+1=0 4x4+16x3+25x2+21x+9=0 16x5-16x4-12x3+12x2+0x-1=0 x5+0x4-5x3+0x2+4x-10=0 x5-8x4+17x3-10x2+0x-1=0 x7+x6-4x5-4x4-2x3-5x2-x-1=0 Nota: Aplicaremos el mtodo de Graeffe a un polinomio cuyo trmino independiente es distinto de cero. Ya que una ecuacin como x3-4x2+x=0, tiene una raz x=0 y por tanto, solamente precisamos calcular las races de la ecuacinx2-4x+1=0. Las races complejas de la ecuacin 16x5-16x4-12x3+12x2+0x-1=0 no salen bien.

Referencias

Wylie. Matemticas superiores para la ingeniera. Ediciones del Castillo. Apndice. B. P. Demidovich, I.A. Maron. Clculo numrico funadamental. Mtodo Lobachevski-Graeffe. Edt. Paraninfo (1977) pgs 202-223 ngel Franco.El mtodo de Graeffe. Un procedimiento para hallar las races de un polinomio. Revista Profesional de Programadores n 39, Abril de 1998, pgs. 38-46.
Cdigo fuente
public class Graeffe { public int n; public double[] raicesReales; public Complejo[] raicesComplejas=new Complejo[4]; public int numReales; public int numComplejas; private double[][] a; private int pot2=1; private int m; private final int MAX_ITER=10; private static final double CERO=0.0001; private double[] moduloComplejas=new double[2]; public Graeffe(double[] coef) { n=coef.length-1; raicesReales=new double[n]; a= new double[MAX_ITER][n+1]; //la primera fila de la tabla guarda los coeficientes del polinomio for(int j=0; j<n+1; j++){ a[0][j]=coef[j]; } for(int m=1; m<MAX_ITER; m++){ for(int j=0; j<n+1; j++){ a[m][j]=0.0; } } numReales=0; numComplejas=0; } private void tabla(){ int k,l, signo; //divide el polinomio por el primer coeficiente, las races no cambian for(int i=1; i<n+1; i++){ a[0][i]/=a[0][0]; } a[0][0]=1.0; m=1;

exterior: do{ //cuadrados for(int i=0; i<n+1; i++){ a[m][i]=a[m-1][i]*a[m-1][i]; if(Double.isInfinite(a[m][i])){ break exterior; } } //dobles productos for(int i=1; i<n; i++){ for(int s=1; s<n/2+1; s++){ k=i-s; l=i+s; if((k<0)||(l>n)) break; //trminos simtricos signo=(s%2==0)? +1: -1; a[m][i]+=signo*2*a[m-1][k]*a[m-1][l]; if(Double.isInfinite(a[m][i])){ break exterior; } } } m++; }while(m<MAX_ITER); m--; //potencia de m de 2 pot2=1; for(int i=1; i<=m; i++){ pot2*=2; } } //valor de un polinomio para una variable real public double valorPolinomio(double x){ double y=0.0; //sucesivas potencias de x, se puede utilizar tambin la funcion Math.pow double[] pot_x=new double[n+1]; pot_x[0]=1.0; for(int i=1; i<n+1; i++){ pot_x[i]=pot_x[i-1]*x; } //valores de los sucesivos trminos for(int i=0; i<n+1; i++){ y+=a[0][i]*pot_x[n-i]; } return y; } public Complejo valorPolinomio(Complejo x){ Complejo y=new Complejo(); for(int i=0; i<n+1; i++){ y=Complejo.suma(y, Complejo.producto(a[0][i], Complejo.potencia(x, (n-i)))); } return y; } private void raizRealSimple(int j){

//valor absoluto de la raz // System.out.println("Raiz simple"); double logaritmo=(Math.log(a[m][j])-Math.log(a[m][j-1]))/pot2; double raiz=Math.exp(logaritmo); //determinacin del signo, y1 o y2 tienen que ser casi cero raicesReales[numReales]=(Math.abs(valorPolinomio(raiz))< Math.abs(valorPolinomio(-raiz)))? raiz : -raiz; numReales++; } private void raizRealDoble(int j){ //valor absoluto de la raz double logaritmo=(Math.log(a[m][j+1])-Math.log(a[m][j-1]))/(2*pot2); double raiz=Math.exp(logaritmo); boolean bPositiva=false, bNegativa=false; if (Math.abs(valorPolinomio(raiz))<CERO){ raicesReales[numReales]=raiz; numReales++; bPositiva=true; } if (Math.abs(valorPolinomio(-raiz))<CERO){ raicesReales[numReales]=-raiz; numReales++; bNegativa=true; } if(bPositiva && !bNegativa){ raicesReales[numReales]=raiz; numReales++; } if(!bPositiva && bNegativa){ raicesReales[numReales]=-raiz; numReales++; } } private void unaRaizCompleja(){ double suma=0.0; for(int i=0; i<numReales; i++){ suma+=raicesReales[i]; } double u, v; u=-(a[0][1]+suma)/2; v=Math.sqrt(moduloComplejas[0]*moduloComplejas[0]-u*u); raicesComplejas[0]=new Complejo(u, v); raicesComplejas[1]=new Complejo(u, -v); } private void dosRaicesComplejas(){ double suma=0.0; double producto=1.0; double inversa=0.0; for(int i=0; i<numReales; i++){ suma+=raicesReales[i]; producto*=raicesReales[i]; inversa+=1/raicesReales[i]; }

double r1=moduloComplejas[0]; double r2=moduloComplejas[1]; double y=-(a[0][1]+suma)/2; int signo=((n-1)%2==0)? +1: -1; double z=signo*a[0][n-1]/(2*producto)-r1*r1*r2*r2*inversa/2; double u1=(y*r1*r1-z)/(r1*r1-r2*r2); double u2=(-y*r2*r2+z)/(r1*r1-r2*r2); double v1=Math.sqrt(r1*r1-u1*u1); double v2=Math.sqrt(r2*r2-u2*u2); raicesComplejas[0]=new Complejo(u1, v1); raicesComplejas[1]=new Complejo(u1, -v1); raicesComplejas[2]=new Complejo(u2, v2); raicesComplejas[3]=new Complejo(u2, -v2); } private boolean cambiaSigno(int j){ double logaritmo; for(int k=2; k<=m; k++){ if(a[k][j]>0) continue; numComplejas++; //mximo dos races complejas, 4 contando sus respectivas conjugadas if(numComplejas<3){ logaritmo=(Math.log(a[m][j+1])-Math.log(a[m][j-1]))/(2*pot2); moduloComplejas[numComplejas-1]=Math.exp(logaritmo); return true; } } return false; } public void hallarRaices(){ tabla(); //el pimer coeficiente a[m][0] es siempre 1 for(int i=1; i<n+1; i++){ //i es la raz if(cambiaSigno(i)){ //raz compleja y su correspondiente conjugada i++; continue; } //races simple y dobles double logaritmo=Math.log(a[m][i])-2*Math.log(a[m-1][i]); if(Math.abs(logaritmo)<CERO){ raizRealSimple(i); }else{ raizRealDoble(i); i++; continue; } } if(numComplejas==1){ unaRaizCompleja(); } if(numComplejas==2){ dosRaicesComplejas(); } }

public void mostrarRaices(){ hallarRaices(); //races reales System.out.println("Races reales"); for(int i=0; i<numReales; i++){ System.out.println((double)Math.round(raicesReales[i]*100)/100+" ---> "+valorPolinomio(raicesReales[i])); } System.out.println(""); //races complejas System.out.println("Races complejas"); for(int i=0; i<numComplejas; i++){ System.out.println(raicesComplejas[2*i]+" ---> "+valorPolinomio(raicesComplejas[2*i])); System.out.println(raicesComplejas[2*i+1]+" ---> "+valorPolinomio(raicesComplejas[2*i])); } System.out.println(""); } } public class RaizPolinomioApp { public static void main(String[] args) { //Ecuacin //a[n]x^n+a[n-1]x^(n-1)+.....+a[3]x^3+a[2]x^2+a[1]x+a[0]=0 double[] coef={1, -4, 1, 6}; Graeffe g=new Graeffe(coef); g.mostrarRaices(); //de mayor a menor grado double[] coef1={1, -7, 16, -12}; g=new Graeffe(coef1); g.mostrarRaices(); double[] coef2={1, -7, 25, -39}; g=new Graeffe(coef2); g.mostrarRaices(); double[] coef3={1, 0, -5, 0, 4, -10}; g=new Graeffe(coef3); g.mostrarRaices(); double[] coef4={1, -6, 11, -7}; g=new Graeffe(coef4); g.mostrarRaices(); double[] coef5={1, 2, 2, 2}; g=new Graeffe(coef5); g.mostrarRaices(); double[] coef6={1, -1, -10, -1, 1}; g=new Graeffe(coef6); g.mostrarRaices(); double[] coef7={4, 16, 25, 21, 9}; g=new Graeffe(coef7); g.mostrarRaices(); double[] coef8={16, -16, -12, 12, 0, 1};

g=new Graeffe(coef8); g.mostrarRaices(); double[] coef9={1, -8, 17, -10, 0, 1}; g=new Graeffe(coef9); g.mostrarRaices(); } } public class Complejo{ private double real; private double imag; public Complejo() { real=0.0; imag=0.0; } public Complejo(double real, double imag){ this.real=real; this.imag=imag; } public static Complejo conjugado(Complejo c){ return new Complejo(c.real, -c.imag); } public static Complejo opuesto(Complejo c){ return new Complejo(-c.real, -c.imag); } public double modulo(){ return Math.sqrt(real*real+imag*imag); } //devuelve el ngulo en grados public double argumento(){ double angulo=Math.atan2(imag, real); if(angulo<0) angulo=2*Math.PI+angulo; return angulo*180/Math.PI; } //suma de dos nmeros complejos public static Complejo suma(Complejo c1, Complejo c2){ double x=c1.real+c2.real; double y=c1.imag+c2.imag; return new Complejo(x, y); } //producto de dos nmeros complejos public static Complejo producto(Complejo c1, Complejo c2){ double x=c1.real*c2.real-c1.imag*c2.imag; double y=c1.real*c2.imag+c1.imag*c2.real; return new Complejo(x, y); } //producto de un complejo por un nmero real public static Complejo producto(Complejo c, double d){ double x=c.real*d; double y=c.imag*d; return new Complejo(x, y); } //producto de un nmero real por un complejo public static Complejo producto(double d, Complejo c){ double x=c.real*d; double y=c.imag*d;

return new Complejo(x, y); } //cociente de dos nmeros complejos //excepcin cuando el complejo denominador es cero public static Complejo cociente(Complejo c1, Complejo c2) throws ExcepcionDivideCero{ double aux, x, y; if(c2.modulo()==0.0){ throw new ExcepcionDivideCero("Divide entre cero"); }else{ aux=c2.real*c2.real+c2.imag*c2.imag; x=(c1.real*c2.real+c1.imag*c2.imag)/aux; y=(c1.imag*c2.real-c1.real*c2.imag)/aux; } return new Complejo(x, y); } //cociente entre un nmero complejo y un nmero real public static Complejo cociente(Complejo c, double d) throws ExcepcionDivideCero{ double x, y; if(d==0.0){ throw new ExcepcionDivideCero("Divide entre cero"); }else{ x=c.real/d; y=c.imag/d; } return new Complejo(x, y); } //el nmero e elevado a un nmero complejo public static Complejo exponencial(Complejo c){ double x=Math.cos(c.imag)*Math.exp(c.real); double y=Math.sin(c.imag)*Math.exp(c.real); return new Complejo(x, y); } //raz cuadrada de un nmero positivo o negativo public static Complejo csqrt(double d){ if(d>=0) return new Complejo(Math.sqrt(d), 0); return new Complejo(0, Math.sqrt(-d)); } //funcin auxiliar para la potencia de un nmero complejo private static double potencia(double base, int exponente){ double resultado=1.0; for(int i=0; i<exponente; i++){ resultado*=base; } return resultado; } //funcin auxiliar para la potencia de un nmero complejo private static double combinatorio(int m, int n){ long num=1; long den=1; for(int i=m; i>m-n; i--){ num*=i; } for(int i=2; i<=n; i++){ den*=i;

} return (double)num/den; } //potencia de un nmero complejo public static Complejo potencia(Complejo c, int exponente){ double x=0.0, y=0.0; int signo; for(int i=0; i<=exponente; i++){ signo=(i%2==0)?+1:-1; //parte real x+=combinatorio(exponente, 2*i)*potencia(c.real, exponente-2*i) *potencia(c.imag, 2*i)*signo; if(exponente==2*i) break; //parte imaginaria y+=combinatorio(exponente, 2*i+1)*potencia(c.real, exponente-(2*i+1)) *potencia(c.imag, 2*i+1)*signo; } return new Complejo(x, y); } //representa un nmero complejo como un string public String toString(){ if(imag>0) return new String((double)Math.round(100*real)/100 +" + "+(double)Math.round(100*imag)/100+"*i"); return new String((double)Math.round(100*real)/100+" - " +(double)Math.round(-100*imag)/100+"*i"); } } class ExcepcionDivideCero extends Exception { public ExcepcionDivideCero() { super(); } public ExcepcionDivideCero(String s) { super(s); } }

También podría gustarte