Zusätzlich zu der Antwort von Elias, die bei Implementierung mit vorzeichenbehafteten Ganzzahlen undefiniertes Verhalten und bei Implementierung mit vorzeichenlosen Ganzzahlen falsche Werte für hohe Eingaben verursacht,
Hier ist eine modifizierte Version der Exponentiation durch Quadrieren, die auch mit vorzeichenbehafteten Ganzzahltypen funktioniert und keine falschen Werte angibt:
#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;
}
Überlegungen zu dieser Funktion:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
Wenn ein Überlauf oder eine Umhüllung stattfinden soll, return 0;
Ich habe verwendet int64_t
, aber jede Breite (signiert oder nicht signiert) kann mit nur geringen Änderungen verwendet werden. Wenn Sie jedoch einen nicht-feste Breite Integer - Typen verwenden müssen, werden Sie ändern müssen , SQRT_INT64_MAX
um (int)sqrt(INT_MAX)
(in dem Fall der Verwendung int
) oder etwas ähnliches, das optimiert werden soll, aber es ist hässlicher, und kein C konstanter Ausdruck. Auch das Casting des Ergebnisses sqrt()
auf ein int
ist aufgrund der Gleitkomma-Präzision bei einem perfekten Quadrat nicht sehr gut, aber da ich keine Implementierung kenne, bei der INT_MAX
- oder das Maximum eines Typs - ein perfektes Quadrat ist, können Sie leben damit.