Ngoài câu trả lời của Elias, nguyên nhân gây ra Hành vi không xác định khi được triển khai với số nguyên đã ký và giá trị không chính xác cho đầu vào cao khi được triển khai với số nguyên không dấu,
đây là phiên bản sửa đổi của lũy thừa theo bình phương cũng hoạt động với các kiểu số nguyên đã ký và không đưa ra các giá trị không chính xác:
#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;
}
Cân nhắc cho chức năng này:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
Nếu bất kỳ tràn hoặc gói sẽ diễn ra, return 0;
Tôi đã sử dụng int64_t
, nhưng bất kỳ chiều rộng (đã ký hoặc không dấu) có thể được sử dụng với ít sửa đổi. Tuy nhiên, nếu bạn cần sử dụng loại số nguyên có chiều rộng không cố định, bạn sẽ cần thay đổi SQRT_INT64_MAX
theo (int)sqrt(INT_MAX)
(trong trường hợp sử dụng int
) hoặc một cái gì đó tương tự, cần được tối ưu hóa, nhưng nó xấu hơn và không phải là biểu thức hằng C. Ngoài ra, kết quả của sqrt()
một kết quả int
là không tốt lắm vì có dấu phẩy động trong trường hợp một hình vuông hoàn hảo, nhưng như tôi không biết về bất kỳ triển khai nào INT_MAX
- hay tối đa của bất kỳ loại nào - là một hình vuông hoàn hảo, bạn có thể sống với.