Soluciones de una ecuación de tercer grado en Excel. Hace algún tiempo expliqué la manera de resolver, esto es, de encontrar la solución de una ecuación lineal de grado uno (ver ver)); en aquel entonces utilicé la herramienta Buscar objetivo. objetivo. Recientemente, Recientemente, a través de un comentario en el blog, un usuario pedía ayuda para saber cómo solucionar una ecuación de tercer grado: ...lo q necesito es encontrar mas de una raíz, t engo un polinomio cubico y necesito las 3 raíces...
He de decir que para encontrar las tres raíces/soluciones de un polinomio cúbico partiré de una hipótesis de trabajo, que el polinomio tiene tres raices; sabemos que una ecuación de tercer grado podría tener hasta tres puntos de corte con el eje X, es decir, hasta tres valores de X donde la ecuación devuelve un valor igual a cero. Inicio el trabajo con un ejemplo de ecuación de tercer grado con tres soluciones. y = 2x3 - 4x2 + 1
A pesar de mi hipótesis inicial, el método de trabajo es válido para cualquier polinomio cúbico. El primer paso es escribir nuestra ecuación de manera que Excel la entienda: =2*POTENCIA(A3;3)-4*POTENCIA(A3;2)+1 con esta fórmula, en un segundo paso, construiremos una gráfica (forma (forma visual de encontrar las soluciones buscadas para nuestra ecuación): ecuación):
Ya en el gráfico podemos ver cuáles son las raíces de la ecuación, pero parece claro que dependerá mucho de los valores de la x que hayamos insertado para construir el gráfico. Se hace necesario, por tanto, tener buena vista, o probar un par de veces, para conseguir el gráfico adecuado a nuestros propósitos. Sin embargo, con el gráfico sólo podemos intuir la forma de la ecuación y más o menos por donde 'caen' las raíces. Para conocer las soluciones exactas nos basaremos en el gráfico recién construido.
Toca ahora construir un modelo sobre el que aplicar la herramienta SOLVER , que será quien nos de nuestras raíces para la ecuación.
Recuperaremos Recuperaremos la fórmula de la ecuación: =2*POTENCIA(K2;3)-4*POTENCIA(K2;2)+1
Fijémonos que en la celda L5 aparece lo que será la celda objetivo en objetivo en el modelo de Solver; y que también he añadido lo que serán dos restricciones o condiciones en las celdas M3 y M4 que asegurarán que Solver no repita las raíces.
Muy importante antes de ejecutar la herramienta Solver será aprovechar el trabajo realizado al construir el gráfico; y es que habrá que 'ayudar' un poco a So lver a que nos devuelva las soluciones correctas. Viendo el gráfico es fácil determinar que la primera raiz (la menor de todas) es negativa y que la segunda y tercera raíz son positivas, obviamente la tercera mayor que la segunda. Realmente con esto sería suficiente, pero si lo estimamos necesario podemos ser más precisos y decir que la primera raiz es un número cercano a -0,50, que la segunda es aproximádamente 0,60 y la tercera 1,90.
Voy a trabajar de una manera general, sin llegar a ayudar a Solver con tanta precisión (probablemente muchas veces no pueda o quiera conocer esos valores). Escribo unos valores genéricos que se adecúen a lo comentado:
Cuanto más próximos sean los valores dados más rápido encontrará Solver las soluciones. Ya terminamos, ya que sólo queda ejecutar Solver y definir sus restricciones. Desde el menú Datos > Análisis > Solver:
Y al resolver logramos por fin nuestras tres soluciones a la ecuación...
Publicado por ExcelForo TEMAS: Buscar objetivo-Solver
http://excelforo.blogspot.com/2010/09/soluciones-de-una-ecuacion-de-tercer.html
RESOLUCIÓN DE ECUACIONES UTILIZANDO MICROSOFT EXCEL 1. Introducción a Excel Excel es un software diseñado para su uso como “hoja de cálculo”. Es decir, permite agilizar la realización de cálculos de diversa índole, siendo una herramienta muy extendida y potente. En este sencillo ejemplo vamos a explicar brevemente como es posible resolver una ecuación cúbica (que es la forma típica de las ecuaciones de estado que vamos a usar en la asignatura) de una manera sencilla. 2. Ejemplo a resolver La función de la que queremos obtener las raíces podría es: 4x3+3x2 –6x –2 = 0 Esta ecuación tiene tres raíces reales, como puede observarse en la figura 1. [pic] Figura 1. Representación gráfica de y=4x3+3x2 –6x –2 3. Resolución en Excel En Excel, a cada una las celdas (que están formadas por la intersección una fila y una columna) se le puede asignar un texto, un número o una operación/función matemática. La asignación de texto o números es directa, mientras que las operaciones van precedidas del signo = [pic] Figura 2. Introducción de datos en Excel
En la figura 2 se observa que se han asignado los coeficientes de la ecuación cúbica a resolver a las celdas B6, C6, D6 y E6. Para calcular el valor de la función (variable y), será necesario especificar un valor de la variable x. Eso se ha hecho en la celda H8. El cálculo 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 ratón 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 función “buscar objetivo”. Esta función se encuentra en Datos→Análisis y si→Buscar objetivo, como
puede observarse en la figura 3.
[pic] Figura 3. Ubicación de la función “buscar objetivo”
El funcionamiento de “buscar objetivo” es sencillo. Una vez seleccionado, los
parámetros 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, sería 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 variación del valor de x). Según la
figura 2 sería la celda H8 Una vez realizado esto, Excel iterará hasta buscar el objetivo. 4. Valor inicial de x Como es bien conocido, la obtención de una raíz u otra de la ecuación cúbica dependerá de la selección 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 función “buscar objetivo”.
Ejercicio: Calcule las tres raíces de la ecuación y=4x3+3x2 –6x –2 Para la resolución de ecuaciones cúbicas de estado, los valores que interesan son los valores menor y mayor de x (que representarían, por ejemplo, el volumen parcial del líquido y del vapor, respectivamente). Las reglas explicadas en clase para la selección de valores iniciales en la resolución iterativa “a mano” de
ecuaciones cúbicas también pueden ser aplicadas para la resolución 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 cómo 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 aplicación será válida sólo en aquellos casos que la combinación 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' . También 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 función: =SUMAPRODUCTO(binario;Cantidades) esta función se encargará de multiplicar fila a f ila, elemento a elemento, los valores del rango 'binario' y del rango 'Cantidades'. Esta celda, será considerada en la configuración como la Celda objetivo. Ejecutamos Solver, desde Datos > Análisis > Solver:
Vemos que hemos seleccionado como celda objetivo la celda $D$2, donde se encontraba la función SUMAPRODUCTO. Además, 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 combinación de cantidades que sumen 415,09. La única condición que damos es que cada uno de los valores del rango 'binario', tras la ejecución de Solver únicamente podrán ser o ceros o unos (0 ó 1), es decir, un número binario. Esto lo conseguimos agregando la siguiente condición:
Ya estamos en disposición de Resolver. Obteniendo la siguiente ventana de información:
El resultado es que ha encontrado la combinación de valores del campo 'Cantidades' que suma 415,09: 415,09 = 126,35 + 71,00 + 117,75 + 99,99
Vemos como Solver ha añadido ceros y unos en el rango 'binario' hasta encontrar la combinación por la que SUMAPRODUCTO(binario; Cantidades) = 415,09
Conciliar en Excel por aproximación con Solver. Tiempo atrás, 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 través de un comentario: ...¿podríamos hacer que las posibilidades de suma fueran por un aproximado de por ejemplo 5 unidades arriba y 5 abajo?...
La respuesta a esta cuestión sería afirmativa, claro está bajo ciertos supuestos, ya que en caso de múltiples coincidencias solver siempre se decantaría 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 más próxima al valor buscado. Importante aclarar, buscamos por aproximación 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 fórmula =A2*B2 para luego acabar sumando estos valores en C8 y D8 =SUMA(C2:C7) y =SUMA(D2:D7); sumas que emplearemos después al Agregar nuestras condiciones de Solver. Importante también es definir correctamente la que será celda objetivo E8, con la fórmula: =ABS(((G2*2)-(D8+C8))/2) sabiendo que nuestro modelo es el siguiente, con la disposición de celdas que vemos en la imagen:
Además de la formulación de la celda $E$8 (futura celda objetivo), es clave determinar cuál es el factor de aproximación, en mi ejemplo será de 2 por encima o por debajo del valor buscado o a
conciliar (27,92); estos valores serán empleados al construir las condiciones de Solver. Ejecutemos la herramienta Solver, así que iremos a la Ficha Datos > Análisis > Solver , y configuraremos los diferentes parámetros:
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), además de restringir que la suma del producto de cada registro por ese valor binario a obtener sea mayor o igual que el mínimo (valor buscado menos la aproximación) y menor o igual que el máximo (valor buscado más la aproximación). Con estas restricciones, al minimizar el modelo desarrollado, conseguiremos llegar a las partidas que mejor se aproximan al valor buscado, esto es a la 'conciliación por aproximación'. Si Aceptamos la configuración, 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 más próximo.
kaz click en la imagen
Para nuestro ejemplo, las partidas cuya suma se aproximan más a 27,92 son 10,00 + 15,00 + 2,90. Por supuesto, este método, sería válido también para la conciliación 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 sería: 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 l a imagen anexa.
Raíces de un polinomio. Método de Graeffe http://www.sc.ehu.es/sbweb/fisica_/numerico/raices/graeffe.xhtml
En esta página, se describe un procedimiento matemático ingenioso para hallar las raíces de un polinomio con gran exactitud. El método 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, descomposición de un problema en tareas que se codifican en forma de funciones, y finalmente, la encapsulación de los datos y las funciones para formar una clase. En muchos campos de las matemáticas es necesario hallar las raíces de un polinomio, por ejemplo, para calcular la integral de una función racional, para calcular las raíces del polinomio característico que son los valores propios de una matriz, etc. Solamente existen fórmulas si el polinomio tiene un grado igual o inferior a cuatro. Excepto para los polinomios de primer y segundo grado, las fórmulas son complicadas, por lo que se emplean procesos de aproximación numérica. Entre los numerosos métodos que existen, el más conocido es quizá el método de Newton. Sin embargo, describiremos un método, realmente ingenioso, que nos proporciona gran exactitud en las raíces de un polinomio. Sea el polinomio a 0 x n + a 1 x n−1 + a 2 x n−2 + a 3 x n−3 + ... a n−1 x+ a n =0
(1)
Hacemos el polinomio más simple dividiendo todos los coeficientes por el primer término de modo que a0 es siempre 1. Supongamos que sus raíces reales y distintas son -r 1 , -r 2 , -r 3 , ...-r n
Al elevar al cuadrado el polinomio y agrupar los términos se obtiene un polinomio de grado 2n a 0 2 ( x n ) 2 −( a 1 2 −2 a 2 a 0 ) ( x n−1 ) 2 +( a 2 2 −2 a 1 a 3 +2 a 4 a 0 ) ( x n−2 ) 2 −( a 3 2 −2 a 2 a 4 +2 a 1 a5 −2 a 6 a 0 ) ( x n−3 ) 2 + ...=0 } (2) Cuyas raíces serán − r 1 2 ,− r 2 2 ,− r
3 2 ... − r n 2
Hemos construido así una nueva ecuación cuyas raíces son numéricamente iguales a los cuadrados de las raíces de la ecuación original. Repitiendo el proceso, se pueden obtener ecuaciones cuyas raíces sean numéricamente
iguales a las potencias cuarta, octava, decimosexta, etc. de las raíces de la ecuación original. El efecto de este proceso de elevar al cuadrado es el de producir ecuaciones cuyas raíces están cada vez más separadas. Por ejemplo, si dos raíces de la ecuación original están entre sí como 5 : 4 sus potencias 128 están en la razón 5128 : 4128, o sea, 2.54 1012: 1, lo que es muy deseable ya que las ecuaciones cuyas raíces están muy separadas se pueden resolver rápidamente con exactitud considerable. Supóngase ahora, que reiterando el proceso de elevación al cuadrado se llega a un polinomio α 0 ( x n ) 2 m + α 1 ( x n−1 ) 2 m + α 2 ( x n−2 ) 2 m + α 3 ( x n−3 ) 2 m + ...
=0
(3)
donde m es el número de veces que se repite el proceso de elevación al cuadrado. Así, si se repite siete veces el proceso de elevación al cuadrado, 2m =27 =128 sería el exponente al que estarían elevados las sucesivas potencias xn , xn-1 , xn-2, ... del polinomio. Sus raíces serán las del polinomio original elevadas al exponente 2 m. − r 1 2 m ,− r 2 2 m ,− r 3 2 m , ... − r n 2 m
Por las relaciones conocidas entre raíces y coeficientes del polinomio, se tiene que α 0 =1 α 1 =-
(suma de las raíces)= r 1 2 m + r 2 2 m + ... + r n 2 m α 2 =(suma de las raíces 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 n−1 2 m r n 2 m α 3=−(suma de las raíces 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 n−2 2 m r n−1 2 m r n 2 m α n = ( −1 ) n (producto de todas las raíces)= r 1 2 m r 2 2 m r 3 2 m ... r n2 m En la suposición 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 símbolo >>> indica mucho mayor que. Las relaciones entre coeficientes y raíces quedarán simplificadas con gran aproximación 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 módulo de r 1 se puede hallar extrayendo la raíz 2 m-ésima de α1 . De la segunda ecuación se obtiene r 2 , y así sucesivamente. La fórmula para obtener el módulo de la raíz r i es | r i |= α i α i−1 2 m En la práctica, hallamos el logaritmo de r i, y luego, calculamos el antilogaritmo del resultado obtenido, de este modo se obtiene el valor absoluto de la raíz r i. log | r i |= log
α i −log
α i−1 2 m (4)
Para determinar el signo, se halla el valor del polinomio original para los valores r i, y -r i, uno de los dos hará que dicho valor sea próximo a cero y por tanto, será la raíz buscada. Cálculo de los coeficientes en las sucesivas iteracciones
Un polinomio cuyas raíces son reales y distintas es el caso más simple que se nos puede presentar. Sea por ejemplo el polinomio x3-4 x2+ x+6,cuyas raíces como se puede comprobar fácilmente por simple sustitución son 3, 2, y -1. En la tabla se observa los coeficientes αi resultantes del proceso de elevación 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 expresión a 1 2 −2 a 2 a 0
El tercer coeficiente α2 mediante la expresión a 2 2 −2 a 1 a 3
El cuarto coeficiente α3 mediante la expresión a 3 2 m
m (2 )
α0
α1
α2
α3
0 (1)
1.0
-4.0
1.0
6.0
1 (2)
1.0
14.0
49.0
36.0
2 (4)
1.0
98.0
1393.0
1296.0
3 (8)
1.0
6818.0
1.6864 10
6
1.6796 10
6
4 (16)
1.0
4.3112 10
2.8212 10
12
2.8211 10
12
7
5 (32)
1.0
1.8553 10
15
7.9587 10
6 (64)
1.0
3.4337 10
30
6.334 10
49
6.334 10
49
7 (128)
1.0
1.179 10
4.012 10
99
4.012 10
99
8 (256)
1.0
1.3901 10
122
1.6096 10
199
1.6096 10
199
9 (512)
1.0
1.9323 10
244
2.5908 10
398
2.5908 10
398
61
24
24
7.9587 10
Podemos observar en la tabla que cada coeficiente en la iteración 9, es aproximadamente el cuadrado del coeficiente en la iteración precedente, habiéndose 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 número m de veces que se repite el proceso de elevación 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 aplicación sucesiva del procedimiento de elevación 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 raíces del polinomio, primero, su valor absoluto mediante la fórmula (4) y luego su signo, y guardarlas en un array unidimensional de dimensión n. 4. Mostrar las raíces 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
Donde MAX_ITER es el número máximo de iteracciones, o de veces que se repite el proceso de elevación al cuadrado. En una función miembro denominada tabla, codificaremos el procedimiento de elevación al cuadrado de un polinomio de grado n. Partiendo del polinomio original (1), obtenemos el polinomio resultante del procedimiento de elevar al cuadrado (3) según el esquema (2). En la expresión (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 fórmula α 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 límite máximo o mínimo para un tipo de dato básico: int, long, o double. Por ejemplo, podemos guardar números 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 límites especificados para un tipo de dato dado. En el código de la función tabla, cuando se supera el valor máximo que puede guardar un dato de tipo double, se interrumpe el proceso de elevación al cuadrado, y se sale fuera del bucle. La función estática isInfinite de la clase Double se encarga de verificarlo devolviendo true si hemos superado dicho límite permitido. exterior: do{ for(int i=0; i
Es necesario emplear un break con una etiqueta para salir al bucle exterior do...while, e interumpir el proceso de elevación al cuadrado. Si
solamente empleamos break salimos del bucle interior for y se continuaría en el bucledo...while el proceso de cálculo. Nos queda ahora, la determinación 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 módulo %en conjunción 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 bucle for. pot2=1; for(int i=1; i<=m; i++){ pot2*=2; }
El código de la función 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 raíces no cambian for(int i=1; in)) break; //términos simétricos 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
Raíces reales y distintas
Un polinomio cuyas raíces son reales y distintas es el caso más simple que se nos puede presentar. Volvemos a estudiar el polinomio x3-4 x2+ x+6, cuyas raíces como se puede comprobar fácilmente por simple sustitución son 3, 2, y -1. En latabla que creamos en el apartado anterior, nos fijamos en la última fila. m
m (2 )
α0
α1
α2
α3
0 (1)
1.0
-4.0
1.0
6.0
9 (512)
1.0
1.9323 10
244
2.5908 10
398
2.5908 10
398
Los módulos de las raíces reales, se calculan mediante la fórmula (4). Para hallar las raíces con gran exactitud tomaremos los coeficientes que figuran en la última fila, resultado de elevar el polinomio a la potencia 512. log r 0=(log(α1)-log(α0))/2m log r 0=(log(1.9323 10244)-log(1))/512 r 0 sale 3 log r 1=(log(α2)-log(α1))/2m log r 1=(log(2.5908 10398)-log(1.9323 10244))/512 r 1 sale 2 log r 2=(log(α3)-log(α2))/2m log r 2=(log(2.5908 10398)-log(2.5908 10398))/512 r 2 sale 1
Para codificar estos cálculos, emplearemos las funciones Math.log que halla el logaritmo de la raíz, y la función recíproca Math.exp, para hallar la raíz. El valor absoluto de la raíz real se guarda en la variable local raiz . private void raizRealSimple(int j){ //valor absoluto de la raíz double logaritmo=(Math.log(a[m][j])-Math.log(a[m][j-1]))/pot2; double raiz=Math.exp(logaritmo); //determinación del signo raicesReales[numReales]=(Math.abs(valorPolinomio(raiz))
Para determinar el signo de la raíz real, hallaremos el valor del polinomio para dos valores raiz y -raiz , uno de los dos tiene que ser cero o muy próximo a cero. Una vez hallada la raíz real, su valor absoluto y su signo, se guarda en el arrayraicesReales. Raíces reales dobles
En el apartado anterior, hemos supuesto que las raíces de un polinomio son reales y distintas, por lo que la aplicación del método de Graeffe es inmediata. Supongamos el polinomio x3-7 x2+16 x-12 que tiene una raíz doble 2, y una simple 3. Examinemos el comportamiento de sus coeficientes en el proceso de elevación al cuadrado en la tabla. Observaremos que el segundo coeficiente α1 se comporta como hemos descrito en el apartado anterior, cada coeficiente en una iteración es aproximadamente el cuadrado de la iteración 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 séptima iteración es 8.024 10 99 y su cuadrado es 6.4384 10199, sin embargo, se obtiene la mitad 3.2192 10199. Lo mismo ocurre en octava iteración 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 señala la presencia de raíces reales dobles. m
m (2 )
α0
α1
α2
α3
0 (1)
1.0
-7.0
16.0
-12.0
1 (2)
1.0
17.0
88.0
144.0
2 (4)
1.0
113.0
2048.0
20736.0
3.4248 10
6
4.2998 10
8
7
5.6465 10
12
1.8488 10
17
15
1.5917 10
25
3.4182 10
34
1.2668 10
50
1.1684 10
69
1.3652 10
138
199
1.8638 10
276
398
3.4737 10
552
3 (8)
1.0
7073.0
4 (16)
1.0
4.3178 10
5 (32)
1.0
1.853 10
6 (64)
1.0
3.4337 10
7 (128)
1.0
1.179 10
8 (256)
1.0
1.3901 10
122
3.2192 10
9 (512)
1.0
1.9323 10
244
5.1817 10
30
61
8.024 10
99
Para obtener la raíz doble, se ha de aplicar la siguiente fórmula que damos sin justificar. La raíz repetida se puede hallar calculando la raíz 2·2m de la razón de los coeficientes que inmediatamente preceden y siguen al coeficiente excepcional. Si i es el coeficiente excepcional, el módulo de la raíz doble se calcula mediante la fórmula | r i |= 2 m+1 α i+1 α i−1
(5)
La codificación de la función raizRealDoble es similar a la función raizRealSimple. Primero, halla el módulo de la raíz aplicando la fórmula (5), y posteriormente, determina su signo. La raíz buscada se guarda dos veces en el arrayraicesReales, y se incrementa dos unidades el contador de raíces reales numReales. private void raizRealDoble(int j){ //valor absoluto de la raíz double logaritmo=(Math.log(a[m][j+1])-Math.log(a[m][j-1]))/(2*pot2); double raiz=Math.exp(logaritmo); //determinación del signo boolean bPositiva=false, bNegativa=false; if (Math.abs(valorPolinomio(raiz))
numReales++; } if(!bPositiva && bNegativa){ raicesReales[numReales]=-raiz; numReales++; }
}
Una raíz compleja y su conjugada
Los polinomios pueden tener también raíces complejas y sus respectivas conjugadas. El caso más simple es el del un polinomio x2+1 que tiene una raíz compleja y su correspondiente conjugada. Sea el polinomio x3-7 x2+16 x-12 que tiene las siguientes raíces 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 iteración, además el valor del coeficiente en una iteración no es aproximadamente igual al cuadrado de su valor en la siguiente iteración, sino la mitad de dicho valor, un comportamiento similar al de las raíces dobles. Al coeficiente α1 le denominaremos coeficiente excepcional. m
m (2 )
α0
α1
α2
α3
0 (1)
1.0
-7.0
25.0
-39.0
1 (2)
1.0
-1.0
79.0
1521.0
2 (4)
1.0
-157.0
9283.0
2.3134 10
3 (8)
1.0
6083.0
8.1259 10
4 (16)
1.0
-1.5882 10
5 (32)
1.0
1.3319 10
18
4.4524 10
6 (64)
1.0
8.8358 10
35
7 (128)
1.0
3.886 10
8 (256)
1.0
7.4134 10
9
71
142
8
12
2.8644 10
25
35
8.2048 10
50
1.9606 10
71
6.7319 10
101
3.8437 10
142
4.5318 10
203
1.4774 10
285
2.0537 10
407
5.952 10
17
5.352 10
6
9 (512)
1.0
2.5411 10
285
2.1827 10
570
4.2177 10
814
Para conocer si un polinomio tiene raíces 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 función miembro denominada cambiaSigno que explora cada columna buscando cambios de signo en el coeficiente de orden j, tras sucesivas iteraciones. Si no detecta ningún cambio de signo devuelve false y si encuentra un cambio de signo, quiere decir, que ha encontrado una raíz compleja y su correspondiente conjugada, añadiéndose una unidad al contador numComplejas. Posteriormente, calcula el módulo de dicha raíz, 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 módulo de las raíces complejas se determina mediante la misma fórmula que las raíces dobles., calculando la raíz 2·2mde la razón de los coeficientes que inmediatamente preceden y siguen al coeficiente excepcional. Para calcular una raíz compleja hemos de determinar su parte real, ya que la parte imaginaria se obtiene a partir de su módulo y de su parte real. Denotemos las raíces complejas como u+vi y u-vi, si conocemos la parte real u, la parte imaginaria v se determina mediante la fórmula v= r 2 − u 2 , donde r es el módulo obtenido a partir de la fórmula (5). Queda, por tanto, determinar la parte real u, mediante la fórmula que daremos sin justificar. u=− 1 2 ( coeficiente de
x n-1 +suma de todas las raíces reales )
El código de la función denominada unaRaizCompleja, calcula primero la suma de todas las raíces reales. Luego, se determina u, y a partir de u se calcula v. La raíz compleja y su correspondiente conjugada se guardan el arrayraicesComplejas. private void unaRaizCompleja(){ double suma=0.0; for(int i=0; i
v=Math.sqrt(moduloComplejas[0]*moduloComplejas[0]-u*u); raicesComplejas[0]=new Complejo(u, v); raicesComplejas[1]=new Complejo(u, -v); }
En esta porción de código, 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 número complejo y como funciones miembro, tiene los constructores, las funciones que suman, restan, multiplican o dividen dos numeros complejos. Dos raíces complejas y sus conjugadas
Supongamos ahora el polinomio x5-4 x4+11 x3+4 x2-10 x-52 que tiene una raíz real 2 y dos raíces 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 además, se comportan de modo similar al de las raíces dobles, signo inequívoco de una raíz compleja. Por tanto, el polinomio tendrá dos raíces complejas y sus respectivas conjugadas, en total cuatro raíces que es el máximo número que permite este procedimiento. m
m (2 )
α0
0 (1)
α1
α2
α3
α4
α5
1.0 -4.0
11.0
4.0
-10-0
-52.0
1 (2)
1.0 -6.0
133.0
652.0
516.0
2704.0
2 (4)
1.0 -230.0
2.6545 10
3 (8)
1.0 -190.0
8.156 10
4 (16)
1.0 -1.6312 10
5 (32) 6 (64)
4
8
2.554 10
5
-3.2598 10
6
7.3116 10
2.3493 10
11
6.8913 10
12
5.346 10
6
13
9
6.6531 10
17
4.3949 10
22
2.2371 10
25
2.8579 10
27
1.0 1.3301 10
18
4.4278 10
35
1.9018 10
45
2.4926 10
50
8.1678 10
54
1.0 8.8357 10
35
1.9605 10
71
3.6165 10
90
3.1066 10
100
6.6714 10
109
3.8437 10
142
1.3079 10
181
4.8255 10
200
4.4507 10
219
1.4774 10
275
1.7107 10
362
1.1643 10
401
1.9809 10
439
7 (128) 1.0 3.886 10
61
8 (256) 1.0 7.4134 10
142
9 (512) 1.0 2.5411 10
285
2.1827 10
570
2.9265 10
724
6.7774 10
801
3.9238 10
Denotaremos las dos raíces complejas y sus respectivas conjugadas como u1±v1i y u2±v2i. Conocidos u1 y u2 se calculav1 y v2 mediante las fórmulas v1=r12−u12
v 2 = r 2 2 − u 2 2
Para determinar u1 y u2 se emplean las siguientes fórmulas u 1 + u 2 =− 1 2 ( coeficiente de x n1 +suma de todas las raíces reales ) u 1 r 2 2 + u 2 r 1 2 = (−1) n−1 a n−1 2(pro ducto de las n-4 raíces reales ) − r 1 2 r 2 2 2 ( suma de las inversas de las n4 raíces reales ) Se trata de un sistema de dos ecuaciones con dos incógnitas de las que se despeja u1 y u2 La función denominada dosRaicesComplejas, calcula la suma de todas las raíces reales, el producto y la suma de las inversas de dichas raíces. Después calcula los segundos miembros de cada una de las dos ecuaciones y los guarda en las variables locales y y z La solución del sistema de dos ecuaciones con dos incógnitas 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
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);
878
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 función discriminadora
La función pública hallaRaices se encarga de llamar a la función 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 iteración, e i el coeficiente: 0 es el índice del coeficiente de mayor grado y n es el índice del término independiente. private boolean cambiaSigno(int j){ double logaritmo; for(int k=2; k<=m; k++){ if(a[k][j]>0) continue; numComplejas++; //máximo dos raíces 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 función cambiaSigno, y pasándole el índice i. Si la función devuelve true, quiere decir que se ha detectado una raíz compleja y su correspondiente conjugada. tabla(); //el pimer coeficiente a[m][0] es siempre 1 for(int i=1; i
Posteriormente, analiza si hay una raíz doble, comprobando la relación entre los valores del coeficiente i en las dos últimas iteraciones. Recuérdese que a[m][i] es habitualmente el cuadrado de a[m-1][i], salvo para los
coeficientes excepcionales. Cuando hay presentes raíces 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 raíces dobles. Cuando la variable cociente de la funcióncambiaSigno es cero (el logaritmo de la unidad es cero) o un valor muy próximo a cero (menor que la constante CEROfijada de antemano), se llama a la función raizRealSimple para hallar la raíz correspondiente al coeficiente i del polinomio. En caso contrario, tendremos una raíz doble y se llamará a la función raizRealDoble para calcularla. //raíces simple y dobles double logaritmo=Math.log(a[m][i])-2*Math.log(a[m-1][i]); if(Math.abs(logaritmo)
La primera verificación se realiza sobre las raíces complejas ya que cumplen una condición más estricta que las raíces dobles, es decir, se comportan como las raíces dobles pero además presentan cambios de signo en las primeras iteraciones, mientras el término cuadrado no domina sobre los dobles productos. Una vez concluido el análisis de cada uno de los coeficientes del polinomio en las sucesivas iteraciones que lo elevan al cuadrado y se han calculado las raíces reales simples y dobles se procede al cálculo de las raíces complejas. Si solamente hay una raíz compleja y su conjugada, se llama a la función unaRaizCompleja. if(numComplejas==1){ unaRaizCompleja(); }
Si hay dos raíces complejas y sus conjugadas, se llama a la función dosRaicesComplejas. if(numComplejas==2){ dosRaicesComplejas(); }
El código completo de la función miembro hallarRaices que calcula todas las raíces de un polinomio se muestra a continuación public void hallarRaices(){ tabla(); //el pimer coeficiente a[m][0] es siempre 1 for(int i=1; i
//raíz compleja y su correspondiente conjugada i++; continue; } //raíces simple y dobles double logaritmo=Math.log(a[m][i])-2*Math.log(a[m-1][i]); if(Math.abs(logaritmo)
Mostrar las raíces calculadas
Primero, se muestran las raíces reales con dos cifras decimales (double)Math.round(raicesReales[i]*100)/100
A continuación, se muestran las raíces complejas System.out.println(raicesComplejas[2*i]);
La función println no solamente imprime objetos de la clase String , sino que también imprime datos numéricos de los tipos básicos y como vemos convierte automáticamente un número complejo en su representación textual, pero para ello hemos de redefinir en dicha clase la función toString miembro de la clase base Object de la cual derivan todas las clases en Java. La llamada implícita a dicha función muestra la parte real seguida de la imaginaria ambas con dos cifras decimales y seguida de la unidad imaginaria i. El código completo de la función mostrarRaices es el siguiente. public void mostrarRaices(){ hallarRaices(); //raíces reales System.out.println("Raíces reales"); for(int i=0; i "+ valorPolinomio(raicesReales[i])); } System.out.println(""); //raíces complejas System.out.println("Raíces complejas"); for(int i=0; i
System.out.println(raice sComplejas[2*i]+" ---> "+ valorPolinomio(raicesComplejas[2*i])); System.out.println(raicesComplejas[2*i+1]+" ---> "+ valorPolinomio(raicesComplejas[2*i])); } System.out.println(""); }
Comprobación de las raíces
La función valorPolinomio halla el valor de un polinomio para un valor real de su variable x. Dicha función 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
Es algo más 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 matemática ha definir las siguientes operaciones: la suma de dos números complejos, el producto de un número real por un número complejo y la potencia de un número complejo. La función valorPolinomio devolverá un número complejo, cuando se le pasa en su único argumento otro número complejo. Su definición en términos de las funciones mencionados es la siguiente. public Complejo valorPolinomio(Complejo x){ Complejo y=new Complejo(); for(int i=0; i
Ejemplos
Para hallar las raíces de un polinomio, primero creamos un array de los coeficientes, de mayor a menor grado. Para el polinomio x3-4 x2+ x+6 se escribirá double[] coef={1, -4, 1, 6};
A continuación, 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 función miembro mostrarRaices, para hallar y mostrar las raíces del polinomio. Graeffe g=new Graeffe(coef); g.mostrarRaices();
Para que practique el lector, se le propone hallar las raíces de los siguientes ecuaciones polinómicas: x3-0 x2-3 x+1=0 x4+ x3-10 x2-34 x-26=0 x4+0 x3+4 x2-3 x+3=0 x3-6 x2+11 x-7=0 x3+2 x2+2 x+2=0 x4- x3-10 x2- x+1=0
4 x4+16 x3+25 x2+21 x+9=0 16 x5-16 x4-12 x3+12 x2+0 x-1=0 x5+0 x4-5 x3+0 x2+4 x-10=0 x5-8 x4+17 x3-10 x2+0 x-1=0 x7+ x6-4 x5-4 x4-2 x3-5 x2- x-1=0 Nota: Aplicaremos el método de Graeffe a un
polinomio cuyo término independiente es distinto de cero. Ya que una ecuación como x3-4 x2+ x=0, tiene una raíz x=0 y por tanto, solamente precisamos calcular las raíces de la ecuación x2-4 x+1=0. Las raíces complejas de la ecuación 16 x5-16 x4-12 x3+12 x2+0 x-1=0 no salen bien.
Referencias
Wylie. Matemáticas superiores para la ingeniería. Ediciones del Castillo. Apéndice. B. P. Demidovich, I.A. Maron. Cálculo numérico funadamental. Método Lobachevski-Graeffe. Edt. Paraninfo (1977) págs 202-223 Ángel Franco. El método de Graeffe. Un procedimiento para hallar las raíces de un polinomio . Revista Profesional de Programadores nº 39, Abril de 1998, págs. 38-46. Código 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
exterior: do{ //cuadrados for(int i=0; in)) break; //términos simétricos 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
//valor absoluto de la raíz // System.out.println("Raiz simple"); double logaritmo=(Math.log(a[m][j])-Math.log(a[m][j-1]))/pot2; double raiz=Math.exp(logaritmo); //determinación 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 raíz 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))
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++; //máximo dos raíces 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
public void mostrarRaices(){ hallarRaices(); //raíces reales System.out.println("Raíces reales"); for(int i=0; i "+valorPolinomio(raicesReales[i])); } System.out.println(""); //raíces complejas System.out.println("Raíces complejas"); for(int i=0; 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) { //Ecuación //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 números 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 números 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 número 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 número 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 números complejos //excepción 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 número complejo y un número 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 número e elevado a un número 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); } //raíz cuadrada de un número 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)); } //función auxiliar para la potencia de un número complejo private static double potencia(double base, int exponente){ double resultado=1.0; for(int i=0; im-n; i--){ num*=i; } for(int i=2; i<=n; i++){ den*=i;