std::pow不适合整数快速幂,因其为浮点设计、精度丢失且效率低;应手写迭代快速幂,利用二进制拆分与位运算,注意取模防溢出。

为什么 pow 不适合整数快速幂
std::pow 是为浮点数设计的,内部走的是数学库近似计算路径,对整数输入不仅慢,还可能因精度丢失导致结果错误(比如 pow(10, 9) 返回 999999999 或 1000000001)。整数幂运算应手写迭代或递归的快速幂,核心是利用二进制拆分指数。
用位运算实现迭代快速幂(推荐)
迭代写法无递归开销、不易栈溢出,且位操作直观:每次检查 exp 的最低位是否为 1,是则累乘当前的 base;然后 base = base * base,exp >>= 1。注意处理负指数需额外逻辑,但整数幂通常默认非负。
示例(模 M 场景常见,防溢出):
long long fast_pow(long long base, long long exp, long long M) {
long long res = 1;
base %= M;
while (exp > 0) {
if (exp & 1) res = (res * base) % M;
base = (base * base) % M;
exp >>= 1;
}
return res;
}- 必须对
base先取模,否则第一次base * base就可能溢出 -
exp & 1比exp % 2 == 1更快,也更符合位运算意图 - 若不需要取模,去掉所有
% M,但务必确认base和结果不会溢出long long
什么时候不能直接用位运算快速幂
快速幂假设运算是结合律成立的(如乘法、矩阵乘、模乘),但不适用于所有“幂”语义场景:
立即学习“C++免费学习笔记(深入)”;
- 自定义类型若
operator*不满足结合律(极少见,但需自查) - 指数为负数且要求返回浮点结果时,不应硬套整数快速幂,而应先算正向再取倒数
- 底数为 0 且指数为 0:数学上未定义,代码中要明确约定返回 1 还是抛异常
-
exp = 0时循环不执行,res = 1正确,这点比递归版本更干净
和递归写法比,差在哪
递归快速幂写起来短:return exp == 0 ? 1 : (exp & 1 ? base * fast_pow(base*base, exp>>1) : fast_pow(base*base, exp>>1)),但它有隐式栈深度(最多 ~64 层对 long long),且编译器未必能完全尾调用优化。迭代版空间复杂度严格 O(1),控制流清晰,更适合嵌入式或性能敏感路径。
真正容易被忽略的是:**所有中间乘法都可能溢出,哪怕最终结果在范围内**——所以模运算不是“可选优化”,而是安全前提;不模的话,必须配合 __int128 或大数库,不能只靠换类型。










