快速幂就是快速的求底数的整数次方,比起朴素的方法O(n)的时间复杂度,其时间复杂度是O(log2n)。这是很不错的一个效率提升。
通常要求一个数X的Y次方,记做X^Y,朴素的计算方法是把X乘Y次得到这个结果。
而快速幂计算的过程是,对于指数Y进行奇偶性的判断。为了方便解释,记做:
ans = base ^exp
如果exp为奇数,那么ans = ans * base;
如果exp为偶数,那么ans = ans
然后每次base = base * base;并且每次循环指数减半,直到指数为0循环结束,ans就是所求结果。
例如求4^9
初始各成员的值分别为:ans = 1, base = 4, exp = 9
1、第一次循环:指数exp=9为奇数,那么
ans = ans * base = 4
base = base * base = 4 ^ 2
指数减半,exp = 4
2、第二次循环:指数exp=4为偶数,那么
ans = ans = 4
base = base * base = 4 ^ 4
指数减半,exp = 2
3、第三次循环:指数exp=2为偶数,那么
ans = ans = 4
base = base * base = 4 ^ 8
指数减半,exp = 1
4、第四次循环:指数exp=1为奇数,那么
ans = ans * base = 4^9
base = base * base = 4 ^ 16
指数减半,exp = 0
循环结束,返回ans即所求结果。
可以看出,快速幂在求指数问题的时候,这里只进行了4次的循环,Log2N加1向下取整,而普通的方法是循环9次进行乘法,当指数非常大的时候,这个差距是越来越大的,O(n)显然是比不上O(log2N)。
快速幂在计算的时候, 指数是成半的减少,并且底数同时也是成倍增加,如果这样:base^1,base^2,base^4,base^8,.....。从两个方面同时计算幂次方。而朴素求幂则是底数线性的增加base^1,base^2,base^3,base^4,.....。底数的增加速度就远不及快速幂,并且指数的减少也是逐一减少。
double Power(double base, int exponent) {
if(exponent >= 0) {
double ans = 1.0;
while(exponent) {
// 判断是偶数还是奇数 和1进行与运算
if(exponent & 1) {
// 如果此时的指数 为1则为奇数
ans = ans * base;
}
base = base *base; //底数进行乘方
exponent = exponent >> 1; //指数减半
}
return ans;
}else {
return 1.0 / Power(base, -1 * exponent); //指数为负数的情况 结果是一个分数
}
}