剑指 Offer 16. 数值的整数次方
题干:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
分析:首先想到的是使用递归进行计算。但是,指数幂容易产生指数爆炸,需要一种方法避免指数爆炸。本题中采用的是快速幂算法。详细讲解可见,非常易懂https://blog.csdn.net/qq_19782019/article/details/85621386
可一步一步分析:产生指数爆炸的主要问题在于指数幂过大,因此需要想办法减小幂指数。以210为例,210 = (2*2)5,这样就将原来的10变为了5(可当作二分);以此类推,45 = 4 x 4^4=4 x 16^2 = 4 x 32^1 = 4 x 32。上述操作可以分为:1、当指数幂为偶数时,底数平方,指数减半; 2、指数幂为奇数时,分离出一个底数之后指数变为偶数,继续1的操作。。到最后可以总结出规律,即2^10实际上为指数为奇数的底数乘积(4 x 32;二者指数均为1)。那么代码可写为:
class Solution {
public:
double myPow(double x, int n) {
double result = 1; // 用来存放指数为奇数的底数乘积
long b1 = n; // 主要是解决 n = -2147483648时, n = -n超出界限
if(n < 0) // n<0时,需修改一下才能适用于下面代码
{
x = 1/x;
b1 = -b1;
}
while(b1 > 0 )
{
if(b1 % 2) // 指数为奇数时,分离出一个底数,再将底数平方,指数减半
{
result = result * x;
}
x = x*x;
b1 = b1/2;
}
return result;
}
};
可进一步修改:
1、奇偶数判断:原先用b1 % 2,现用b1 & 1(结果为0,偶数;结果为1,奇数)
2、除2操作,b1>>1;左移一位相当于除以2.
class Solution {
public:
double myPow(double x, int n) {
double result = 1; // 用来存放指数为奇数的底数乘积
long b1 = n; // 主要是解决 n = -2147483648时, n = -n超出界限
if(n < 0) // n<0时,需修改一下才能适用于下面代码
{
x = 1/x;
b1 = -b1;
}
while(b1 > 0 )
{
if(b1 & 1) // 指数为奇数时,分离出一个底数,再将底数平方,指数减半
{
result = result * x;
}
x = x*x;
b1 >>= 1;
}
return result;
}
};