Además de la respuesta de Elias, que causa un comportamiento indefinido cuando se implementa con enteros con signo, y valores incorrectos para una entrada alta cuando se implementa con enteros sin signo,
Aquí hay una versión modificada de Exponentiation by Squaring que también funciona con tipos enteros con signo y no da valores incorrectos:
#include <stdint.h>
#define SQRT_INT64_MAX (INT64_C(0xB504F333))
int64_t alx_pow_s64 (int64_t base, uint8_t exp)
{
int_fast64_t base_;
int_fast64_t result;
base_ = base;
if (base_ == 1)
return 1;
if (!exp)
return 1;
if (!base_)
return 0;
result = 1;
if (exp & 1)
result *= base_;
exp >>= 1;
while (exp) {
if (base_ > SQRT_INT64_MAX)
return 0;
base_ *= base_;
if (exp & 1)
result *= base_;
exp >>= 1;
}
return result;
}
Consideraciones para esta función:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
Si se va a producir un desbordamiento o envoltura, return 0;
Solía int64_t
, pero cualquier ancho (con o sin signo) se puede usar con poca modificación. Sin embargo, si necesita usar un tipo entero de ancho no fijo, deberá cambiar SQRT_INT64_MAX
por (int)sqrt(INT_MAX)
(en el caso de usar int
) o algo similar, que debe optimizarse, pero es más feo y no una expresión constante C. Además, emitir el resultado de sqrt()
a int
no es muy bueno debido a la precisión de coma flotante en el caso de un cuadrado perfecto, pero como no conozco ninguna implementación donde, INT_MAX
o el máximo de cualquier tipo, sea un cuadrado perfecto, puedes vivir con ese.