Selain jawaban oleh Elias, yang menyebabkan Perilaku Tidak Terdefinisi ketika diimplementasikan dengan bilangan bulat yang ditandatangani, dan nilai yang salah untuk input tinggi ketika diimplementasikan dengan bilangan bulat yang tidak ditandatangani,
di sini adalah versi modifikasi dari Exponentiation by Squaring yang juga berfungsi dengan tipe integer yang ditandatangani, dan tidak memberikan nilai yang salah:
#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;
}
Pertimbangan untuk fungsi ini:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
Jika terjadi overflow atau pembungkus, return 0;
Saya menggunakan int64_t
, tetapi lebar apa pun (ditandatangani atau tidak ditandatangani) dapat digunakan dengan sedikit modifikasi. Namun, jika Anda perlu menggunakan tipe integer lebar tidak-tetap, Anda perlu mengubahnya SQRT_INT64_MAX
dengan (int)sqrt(INT_MAX)
(jika menggunakan int
) atau sesuatu yang serupa, yang harus dioptimalkan, tetapi lebih jelek, dan bukan ekspresi konstan C. Juga casting hasil dari sqrt()
ke int
tidak terlalu baik karena precisi floating point dalam kasus kuadrat sempurna, tetapi karena saya tidak tahu implementasi apa pun di mana INT_MAX
- atau maksimum jenis apa pun - adalah kuadrat sempurna, Anda dapat hidup dengan itu.