В дополнение к ответу Элиаса, который приводит к неопределенному поведению при реализации с целыми числами со знаком и неверным значениям для высокого ввода при реализации с целыми числами без знака,
вот модифицированная версия возведения в степень по квадрату, которая также работает со знаковыми целочисленными типами и не дает неправильных значений:
#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
) или что-то подобное, что должно быть оптимизировано, но это уродливее, а не константное выражение C. Также приведение результата sqrt()
к int
не очень хорошо из-за точности с плавающей запятой в случае идеального квадрата, но я не знаю ни одной реализации, где INT_MAX
- или максимум любого типа - это идеальный квадрат, с этим можно жить.