На додаток до відповіді Elias, яка спричиняє не визначену поведінку при реалізації з підписаними цілими числами, і неправильні значення для високого введення, коли реалізовано з непідписаними цілими числами,
ось модифікована версія Exponentiation by Squaring, яка також працює з підписаними цілими типами і не дає неправильних значень:
#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;
}
Розгляд цієї функції:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
Якщо відбудеться якийсь перелив або обгортання, return 0;
Я використовував int64_t
, але будь-яку ширину (з підписом або без підпису) можна використовувати з незначними змінами. Однак, якщо вам необхідно використовувати не фіксовану ширину целочисленного типу, то потрібно змінити SQRT_INT64_MAX
шлях (int)sqrt(INT_MAX)
(в разі використання int
) або щось подібне, які повинні бути оптимізовані, але це потворніше, а не вираз константи С. Також виведення результату sqrt()
на int
не дуже добре через точність точок з плаваючою точкою у випадку ідеального квадрата, але, як я не знаю жодної реалізації, де INT_MAX
- або максимум будь-якого типу - ідеальний квадрат, ви можете жити З цим.