如果用递归的方法求幂, 代码可以是这样的:
double Pow(double x, unsigned int n)
{
if (n == 0)
return 1;
if (n == 1)
return x;
if (n & 1 == true) // 如果n是奇数
return Pow(x * x, n / 2) * x;
else // 如果n是偶数
return Pow(x * x, n / 2);
}
注意:
- n若为一个奇数,那么它对应的二进制最后一位一定是1,与上1最终一定是1
- 上面的n为非负,如果要求负数次幂,可以先求正数次幂再用1除之
上述方法虽然简单, 但是效率并不高. 因为函数调用的代价非常昂贵. 用循环实现的效率更高.
用循环做的话,当然不能直接死乘。举个例子:
直接乘要做998次乘法,效率很低。但事实上可以这样做,先求出2^k次幂:
再相乘:
这样只要做16次乘法。即使加上一些辅助的存储和运算,也比直接乘高效得多(尤其如果这里底数是成百上千位的大数字的话)。
我们发现,把999转为2进制数:1111100111,其各位就是要乘的数。
再举一个例子帮助理解,其中次角标2代表二进制。
因此就可以写出下面的非递归版代码:
double Pow(double x, int n)
{
double result = 1;
while (n)
{
if (n & 1) // 等价于判断n的末位是不是1
result *= x;
n >>= 1; // 将n右移一位,即遍历原n的二进制的每一位
x *= x; // n右移了一位,x补上
}
return result;
}