Uno de los problemas con el método de Newton es que requiere una operación de división en cada iteración, que es la operación entera básica más lenta.
Sin embargo, el método de Newton para la raíz cuadrada recíproca no. Si es el número para el que desea encontrar , repita:1x1x√
ri+1=12ri(3−xr2i)
Esto a menudo se expresa como:
d i = 1 - w i x r i + 1 = r i + r i d i
wi=r2i
di=1−wix
ri+1=ri+ridi2
Eso son tres operaciones de multiplicación. La división por dos se puede implementar como un desplazamiento a la derecha.
Ahora el problema es quer no es un número entero. Sin embargo, puede manipularlo como tal mediante la implementación de punto flotante manualmente, y haciendo un montón de operaciones de desplazamiento para compensar cuando sea apropiado.
Primero, cambiemos la escala de :x
x′=2−2ex
donde nos gustaría que sea mayor que, pero cercano a, . Si ejecutamos el algoritmo anterior en lugar de , encontramos . Entonces, . 1 x ′ x r = 1x′1x′x√r=1x√′x−−√=2erx′
Ahora dividamos en una mantisa y exponente:r
ri=2−eir′i
donde es un número entero. Intuitivamente, representa la precisión de la respuesta.r′iei
Sabemos que el método de Newton duplica aproximadamente el número de dígitos significativos precisos. Entonces podemos elegir:
ei+1=2ei
Con un poco de manipulación, encontramos:
ei+1=2ei
wi=r′i2
x′i=x22e−ei+1
di=2ei+1−w′ix′i2ei+1
r′i+1=2eir′i−r′idi2ei+1
En cada iteración:
x−−√≈r′ix2e+ei
Como ejemplo, intentemos calcular la raíz cuadrada de . Sabemos que la respuesta es . La raíz cuadrada recíproca es , por lo que estableceremos (esta es la escala del problema) y para nuestra conjetura inicial elegiremos y . (Es decir, elegimos para nuestra estimación inicial de ).x=2632312–√12√2−31e=31r′0=3e0=23412√
Entonces:
e1=4,r′1=11
e2=8,r′2=180
e3=16,r′3=46338
e4=32,r′4=3037000481
Podemos determinar cuándo dejar de iterar comparando con ; Si he calculado correctamente, debería ser lo suficientemente bueno. Sin embargo, nos detendremos aquí y encontraremos:eieei>2e
263−−−√≈3037000481×263231+32=3037000481
La raíz cuadrada entera correcta es , por lo que estamos bastante cerca. Podríamos hacer otra iteración o una iteración final optimizada que no duplique . Los detalles se dejan como ejercicio.3037000499ei
Para analizar la complejidad de este método, tenga en cuenta que multiplicar dos enteros de bits requiere operaciones . Sin embargo, hemos organizado las cosas para que . Por lo que la multiplicación para calcular multiplica dos números de bits para producir un número de bits, y los otros dos multiplicaciones multiplicar dos números -bit para producir una -número de bit.bO(blogb)r′i<2eiwieiei+1ei+12ei+1
En cada caso, el número de operaciones por iteración es , y se requieren iteraciones . La multiplicación final está en el orden de las operaciones . Entonces, la complejidad general son las operaciones , que es subcuadrática en el número de bits en . Eso cumple todos los requisitos.O ( log e ) O ( 2 e log 2 e ) O ( e log 2 e ) xO(eilogei)O(loge)O(2elog2e)O(elog2e)x
Sin embargo, este análisis esconde un principio importante que todos los que trabajan con enteros grandes deben tener en cuenta: debido a que la multiplicación es superlineal en el número de bits, cualquier operación de multiplicación solo debe realizarse en enteros que tengan aproximadamente la magnitud de la precisión actual (y , Podría agregar, deberías intentar multiplicar números que tengan un orden de magnitud similar). Usar enteros más grandes que eso es una pérdida de esfuerzo. Los factores constantes importan, y para los enteros grandes, importan mucho.
Como observación final, dos de las multiplicaciones son de la forma . Claramente es un desperdicio calcular todos los bits de solo para tirar de ellos con un desplazamiento a la derecha. La implementación de un método de multiplicación inteligente que tenga esto en cuenta también se deja como un ejercicio. abcab2cabc