La forma más eficiente de implementar una función de potencia basada en números enteros pow(int, int)

Resuelto Doug T. asked hace 16 años • 20 respuestas

¿Cuál es la forma más eficiente de elevar un número entero a la potencia de otro número entero en C?

// 2^3
pow(2,3) == 8

// 5^5
pow(5,5) == 3125
Doug T. avatar Sep 19 '08 19:09 Doug T.
Aceptado

Exponenciación al cuadrado.

int ipow(int base, int exp)
{
    int result = 1;
    for (;;)
    {
        if (exp & 1)
            result *= base;
        exp >>= 1;
        if (!exp)
            break;
        base *= base;
    }

    return result;
}

Este es el método estándar para realizar una exponenciación modular para números enormes en criptografía asimétrica.

Elias Yarrkov avatar Sep 19 '2008 12:09 Elias Yarrkov

Tenga en cuenta que la exponenciación al cuadrado no es el método más óptimo. Probablemente sea lo mejor que puedes hacer como método general que funciona para todos los valores de exponente, pero para un valor de exponente específico podría haber una secuencia mejor que necesite menos multiplicaciones.

Por ejemplo, si quieres calcular x^15, el método de exponenciación elevando al cuadrado te dará:

x^15 = (x^7)*(x^7)*x 
x^7 = (x^3)*(x^3)*x 
x^3 = x*x*x

Esto es un total de 6 multiplicaciones.

Resulta que esto se puede hacer usando "solo" 5 multiplicaciones mediante exponenciación en cadena de suma .

n*n = n^2
n^2*n = n^3
n^3*n^3 = n^6
n^6*n^6 = n^12
n^12*n^3 = n^15

No existen algoritmos eficientes para encontrar esta secuencia óptima de multiplicaciones. De Wikipedia :

El problema de encontrar la cadena de suma más corta no puede resolverse mediante programación dinámica porque no satisface el supuesto de subestructura óptima. Es decir, no es suficiente descomponer la potencia en potencias más pequeñas, cada una de las cuales se calcula mínimamente, ya que las cadenas de suma para las potencias más pequeñas pueden estar relacionadas (para compartir cálculos). Por ejemplo, en la cadena de suma más corta para a¹⁵ anterior, el subproblema para a⁶ debe calcularse como (a³)² ya que a³ se reutiliza (a diferencia de, digamos, a⁶ = a²(a²)², que también requiere tres multiplicaciones ).

Pramod avatar Sep 20 '2008 18:09 Pramod

Si necesitas elevar 2 a una potencia. La forma más rápida de hacerlo es cambiar de bits mediante la potencia.

2 ** 3 == 1 << 3 == 8
2 ** 30 == 1 << 30 == 1073741824 (A Gigabyte)
Jake avatar Mar 17 '2011 21:03 Jake

Aquí está el método en Java.

private int ipow(int base, int exp)
{
    int result = 1;
    while (exp != 0)
    {
        if ((exp & 1) == 1)
            result *= base;
        exp >>= 1;
        base *= base;
    }

    return result;
}
user1067920 avatar May 09 '2012 13:05 user1067920