Além da resposta de Elias, que causa Comportamento indefinido quando implementado com números inteiros assinados e valores incorretos para entrada alta quando implementada com números inteiros não assinados,
aqui está uma versão modificada da exponenciação por esquadro que também funciona com tipos inteiros assinados e não fornece valores incorretos:
#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;
}
Considerações para esta função:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
Se ocorrer algum transbordamento ou encapsulamento, return 0;
Eu usei int64_t
, mas qualquer largura (assinada ou não) pode ser usada com poucas modificações. No entanto, se você precisa usar um tipo inteiro não de largura fixa, você terá de mudar SQRT_INT64_MAX
por (int)sqrt(INT_MAX)
(no caso de usar int
) ou algo semelhante, que deve ser otimizado, mas é mais feio, e não uma expressão C constante. Também converter o resultado de sqrt()
para um int
não é muito bom por causa da precissão de ponto flutuante no caso de um quadrado perfeito, mas como não conheço nenhuma implementação em que INT_MAX
- ou o máximo de qualquer tipo - seja um quadrado perfeito, você pode viver com isso.