1. 前情
在 第二章 幂运算 中,我们知道了如何利用递归快速的求解幂运算。
虽然简单,但是效率不高,因为函数调用的代价非常昂贵,如果将递归改成迭代循环,则会进一步的提升效率。
2. 代码实现
自己写的
#include <bits/stdc++.h>
using namespace std;
int main()
{
int x=2;
int n=10;
int arr[10]={0};//用于存储n每一次/2变换之前是奇数还是偶数
int i=1;
while(n>1){//当n=1时,循环结束
arr[i++]=n%2;
n/=2;
}
int res=x;
for(int j=i-1;j>0;j--){
if(arr[j]==1){
res=res*res*x;
}else if(arr[j]==0){
res=res*res;
}
}
cout<<"res="<<res<<endl;
}
优化后的
//循环求幂显现
double Pow2(double x, unsigned int n)
{
double result = 1;
while (n)
{
if (n & 1) // 等价于 if (n % 2 != 0)
result *= x;
n >>= 1;
x *= x;
}
return result;
}
这个代码将上文代码中的两个循环捏合到一起,并抛弃数组,用位运算来取二进制的最后一位,进一步的提升了效率。
注意:用位运算来取二进制的最后一位 和上文代码中数组的标志位是一一对应的(数组末尾的数对应开始位运算的倒数第二位)。
3. 参考
4. 习题 2.17
根据上述分析,在实际代码中(优化后的),N=0,乘法次数为0,N=1,乘法次数为2.
若b(N)为N中二进制表示中数字1的个数,在代码中乘法次数为:
logN(向上取整)+b(N)。
答案中,因为少算了 result 从1到n的过程(1次)和少算了while循环中 x的最后一次自乘(准确来说没有必要自乘,但是自乘保证了程序的一致性),所以答案是: