He estado aprendiendo sobre la exponenciación rápida cuando encontré este algoritmo:
int expo(int a, int b) {
int result = 1;
while (b) {
if (b%2==1) {
result *= a;
}
b /= 2;
a *= a;
}
return result;
}
Se supone que esto calcula $a^b$ en tiempo logarítmico, pero no pude entender ni encontrar en ningún lugar cómo llegar a este procedimiento, aparte de notar que (esta fórmula en particular no me ayudó a entender por qué el algoritmo es correcto):
$$ x^n = \begin{cases} 1 & \text{si $n=0$} \\ \frac{1}{x}^{-n} & \text{si $n<0$} \\ x \cdot \left( x^{\frac{n-1}{2}} \right)^2 & \text{si $n$ es impar} \\ \left( x^{\frac{n}{2}} \right)^2 & \text{si $n$ es par} \end{cases} $$
Por lo que entiendo, la transición de esta identidad particular al algoritmo real es bastante obvia, pero sinceramente no lo entiendo y he trabajado manualmente en bastantes ejemplos para este algoritmo.
¿Alguien puede explicar?
3 votos
Ejecuta el bucle manualmente para, por ejemplo, $b = 5$. Pista: $a^5 = a^{4+1} = (a^2)^2 \cdot a$. Observa que
b%2 == 1
cuando el $n^{th}$ bit está encendido en la representación binaria de $b$.0 votos
¿Eso equivale a algo más que el hecho de que $b$ sea impar en ese caso?
0 votos
Sí. Espero que la respuesta publicada lo explique mejor.
2 votos
¿Has leído el artículo de Wikipedia sobre este algoritmo? es.wikipedia.org/wiki/Exponenciación_por_cuadrados
0 votos
Sería muy útil si pudieras editar tu respuesta para incluir dónde tropezaste con este fragmento
0 votos
La identidad en la pregunta relaciona $x^n$ con exponentes más bajos ($n/2$, etc.) y forma la base de la exponenciación binaria de izquierda a derecha, que procesa los bits del exponente ($n$) de MSB a LSB. Sin embargo, el algoritmo publicado es el algoritmo binario de derecha a izquierda (y las identidades relevantes ya están disponibles en las respuestas).