Vamos a usar el método de Newton para construir una calculadora sencilla que calcule, de momento, el inverso, la raíz cuadrada y la raíz cúbica de un número dado.
Solo se podrán usar sumas, restas y multiplicaciones para aproximar el resultado.
Para la interfaz vamos a usar PyQt
, un "biding" de Python
para Qt
. El código del modelo, implementando una calculadora sencilla se puede bajar aquí (Qt4
) y aquí (Qt5
).
Comprueba la versión que necesitas escribiendo en el terminal
$ qmake --version
Una vez guardado el fichero en una carpeta, abrir el terminal y ejecutarlo:
$ python calculadora0_Qt4.py
El ejercicio consiste en sustituir la función división "/" en calculadora0.py
por una función definida por el alumno basada en el método de Newton que sólo utilice sumas y multiplicaciones.
Después de la suma y la multiplicación, la siguiente operación de bajo nivel entre dos números es la división.
Para calcular $\displaystyle\frac{a}{b}$ haremos $\displaystyle\frac{a}{b} = a \frac{1}{b}$ (multiplicación de dos números).
Entonces, para calcular $\displaystyle\frac{1}{b}$ definimos la función $\displaystyle f(x) = \frac{1}{x} -b$, de forma que $\displaystyle f(\alpha) = 0$ implica $ \displaystyle \alpha = \frac{1}{b}$.
Se puede deducir facilmente que entonces, la fórmula iterativa correspondiente para calcular la raíz de $f(x)=0$. La función de iteración de Newton será
$$ g(x)=x-\frac{f(x)}{f'(x)} = x-\frac{\frac{1}{x} -b}{-\frac{1}{x^2}} = x-\frac{x-bx^2}{-1} = x+(x-bx^2)=2x-bx^2=x(2-bx) $$es decir, podemos obtener el inverso de $b$ utilizando la sucesión
$$ x_{n+1} = x_n (2-b x_n), $$que sólo utiliza sumas y multiplicaciones.
La convergencia del método de Newton depende de la elección del dato inicial $x_0$. ¿Cómo lo elegimos?
La fórmula de arriba se corresponde con una iteración de punto fijo de la función $g(x) = x(2-bx)$. Por lo tanto, si $\left|g'(x)\right| < 1$ sabemos que el método es convergente. Esto nos lleva a establecer la condición
$$ \frac{1}{2b} < x_0 < \frac{3}{2b},$$y entonces, un buen punto inicial es el inverso de la potencia de diez mayor que el número más cercana.
Por ejemplo, si $b=345$, tomamos $x_0 = 0.001$, porque $0.001$ es el inverso de $1000$, que es la potencia de diez mayor más cercana por arriba al número, $345\lt 1000 = 10^3$. Aunque la condición suficiente no se satisface en este caso, no está lejos de cumplirse.
Escribir una función que calcule el inverso de un número por el método de Newton. De momento, escribir la función de Python que calcula el inverso. Guardarla en un fichero llamado libCalculadora.py (vamos a ir almacenando en este fichero las funciones para la calculadora).
El argumento de entrada debe ser un string que contenga el número, como '-73.034' y la salida debe ser un número en punto flotante. Como criterio de parada, usar el error absoluto entre dos iteraciones con tolerancia tol = 1.e-16
.
La primera parte es calcular el punto inicial, $x_0$. Será siempre una potencia de $10$, donde la potencia es un entero con signo determinado por el "orden" de $b$.
Para ello:
1
ó -1
en una variable.La segunda parte es usar el método de Newton para aproximar la raíz de la función $f(x)$ dada anteriormente, utilizando, para ello la función de iteración de punto fijo $g(x)=x(2-bx)$. Cuando se dé el resultado, recordar multiplicar por el signo del argumento de entrada.
Un ejemplo de ejecución de la función es la siguiente:
from libCalculadora import inverso # Función inversa contenida en nuestro módulo libCalculadora
numero0 = '-0.02'
x0 = inverso(numero0)
Más ejemplos:
numero0 = '-.02'
x0 = inverso(numero0)
numero0 = '-0000.01'
x0 = inverso(numero0)
numero0 = '-0.01'
x0 = inverso(numero0)
numero0 = '-23.01'
x0 = inverso(numero0)
numero0 = '-0023.01'
x0 = inverso(numero0)
Continuar la construcción de la calculadora añadiéndole la raíz cuadrada y la cúbica. Guardar las funciones correspondientes en el fichero libCalculadora.py. Recordar que sólo se pueden usar sumas y multiplicaciones. Por lo tanto, para la división, usar la función definida para calcular el inverso de un número.
Una vez construídas las funciones, añadir los botones correspondientes en el fichero calculadoraNewton.py.