¿Cómo evitar la cancelación catastrófica en la función python?

13

Tengo problemas para implementar una función numéricamente. Sufre el hecho de que a valores de entrada grandes el resultado es un número muy grande multiplicado por un número muy pequeño. No estoy seguro de si la cancelación catastrófica es el término correcto, así que corríjame si es así. Evidencia de que algo va mal:

ingrese la descripción de la imagen aquí

¿Cómo puedo evitar las oscilaciones y la asignación de 0.0 para entradas más grandes de 6?

Aquí está mi función:

import numpy as np

def func(x):
    t = np.exp(-np.pi*x)
    return 1/t*(1-np.sqrt(1-t**2))
Dipolo
fuente

Respuestas:

31

De hecho, esto se llama cancelación catastrófica. De hecho, este caso particular es muy fácil: reescribe la función usando la expresión equivalente numéricamente estable Como probablemente necesite una referencia, esto se discute en la mayoría de los libros de texto de métodos numéricos en relación con la fórmula para resolver ecuaciones cuadráticas (esa fórmula en su forma estándar es numéricamente inestable para algunos valores de parámetros). La forma de deshacerse de es multiplicar y dividir por . Aquí hay una comparación:

t1+1-t2.
1-1-t21+1-t2

ingrese la descripción de la imagen aquí

Kirill
fuente
¡Fantástico! ¿Me puede recomendar uno de esos libros si se describen estas técnicas?
Dipolo
2
@Jack "Precisión y estabilidad de los algoritmos numéricos" es un buen libro de nivel superior. Cualquier libro de texto introductorio discutirá esto también.
Kirill
Me gustaría saber si utilizó Wolfram Mathematica para dibujar este gráfico. THX :)
xyz
¿Conoces referencias que recopilen y / o discutan trucos similares para reescribir expresiones matemáticas en formas matemáticamente equivalentes que reduzcan la pérdida de importancia? Leí el libro de Higham, pero la discusión es general y todos los capítulos posteriores son sobre álgebra lineal (que no es mi tema en este momento).
Becko
@becko Es bastante ad hoc en mi experiencia. Es mucho más fácil hacerlo si tiene una forma de probar su fórmula con las respuestas correctas (incluso si las genera con una aritmética de precisión extra), de modo que no busque inestabilidad numérica sin tener primero casos de prueba fallidos. Y si funciona para todas las entradas conocidas, no hay ningún problema real si la inestabilidad numérica está presente en algún lugar o no.
Kirill