Escriba un programa autónomo que, cuando se le da un polinomio y un límite, encontrará todas las raíces reales de ese polinomio en un error absoluto que no exceda el límite.
Restricciones
Sé que Mathematica y probablemente algunos otros idiomas tienen una solución de un solo símbolo, y eso es aburrido, por lo que debe atenerse a las operaciones primitivas (suma, resta, multiplicación, división).
Hay cierta flexibilidad en los formatos de entrada y salida. Puede recibir información a través de stdin o argumentos de línea de comandos en cualquier formato razonable. Puede permitir la coma flotante o requerir que se use alguna representación de números racionales. Puede tomar el límite o el recíproco del límite, y si está utilizando coma flotante, puede suponer que el límite no será inferior a 2 ulp. El polinomio debe expresarse como una lista de coeficientes monomiales, pero puede ser big o little endian.
Debe poder justificar por qué su programa siempre funcionará (problemas de módulo numérico), aunque no es necesario proporcionar pruebas completas en línea.
El programa debe manejar polinomios con raíces repetidas.
Ejemplo
x^2 - 2 = 0 (error bound 0.01)
La entrada podría ser, por ejemplo
-2 0 1 0.01
100 1 0 -2
1/100 ; x^2-2
La salida podría ser, por ejemplo
-1.41 1.42
pero no
-1.40 1.40
ya que tiene errores absolutos de aproximadamente 0.014 ...
Casos de prueba
Simple:
x^2 - 2 = 0 (error bound 0.01)
x^4 + 0.81 x^2 - 0.47 x + 0.06 (error bound 10^-6)
Raíz múltiple:
x^4 - 8 x^3 + 18 x^2 - 27 (error bound 10^-6)
El polinomio de Wilkinson:
x^20 - 210 x^19 + 20615 x^18 - 1256850 x^17 + 53327946 x^16 -1672280820 x^15 +
40171771630 x^14 - 756111184500 x^13 + 11310276995381 x^12 - 135585182899530 x^11 +
1307535010540395 x^10 - 10142299865511450 x^9 + 63030812099294896 x^8 -
311333643161390640 x^7 + 1206647803780373360 x^6 -3599979517947607200 x^5 +
8037811822645051776 x^4 - 12870931245150988800 x^3 + 13803759753640704000 x^2 -
8752948036761600000 x + 2432902008176640000 (error bound 2^-32)
NB Esta pregunta estuvo en el Sandbox durante aproximadamente 3 meses. Si cree que fue necesario mejorar antes de publicar, visite el Sandbox y comente las otras preguntas propuestas antes de que se publiquen en Main.
fuente
fractions.Fraction
(un tipo racional)? (c) ¿Tenemos que manejar polinomios de grado <1? (d) ¿Podemos suponer que el coeficiente principal es 1?Respuestas:
Mathematica, 223
Esta solución implementa el método Durand-Kerner para resolver polinomios. Tenga en cuenta que esta no es una solución completa (como se mostrará a continuación) porque todavía no puedo manejar el polinomio de Wilkinson con la precisión especificada. Primero una explicación de lo que estoy haciendo:
#[[i]]-p[#[[i]]]/Product[If[i!=j,#[[i]]-#[[j]],1],{j,l}]&
: Por lo tanto, la función calcula para cada índicei
la próxima aproximación de Durand-Kerner. Luego, esta línea se encapsula en una Tabla y se aplica usando un NestWhile a los puntos de entrada generados porTable[(0.9+0.1*I)^i,{i,l}]
. La condición en NestWhile es que el cambio máximo (en todos los términos) de una iteración a la siguiente es mayor que la precisión especificada. Cuando todos los términos han cambiado menos que esto, NestWhile finaliza yRe@Select
elimina los ceros que no se encuentran en la línea real.Salida de ejemplo:
Como probablemente pueda ver, cuando el grado aumenta, este método comienza a rebotar alrededor de los valores correctos, nunca realmente se dirige completamente. Si configuro la condición de detención de mi código para que sea más estricta que "de una iteración a la siguiente, las suposiciones no cambian más que epsilon", entonces el algoritmo nunca se detiene. ¿Supongo que debería usar Durand-Kerner como entrada al método de Newton?
fuente