- 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方
- 保证base和exponent不同时为0
- 第一种思路是常规思路,也是笨办法,就是累乘,最容易想到(方法一),但是这种方法很慢
-
假如我们要求的是$3^{999}$,那么累乘的话效率也太低了,于是我们可以借助乘方的运算性质:
-
按上面的方法,我们只需要用某种快速方法把一系列$3^{(2^{k})}$算出来(一个整数的2次方相当于左移1位),就只需要算7次乘法。将幂也就是$999$转换成二进制(111 110 0111)以后,所有为1的位置对应的二进制权值就是所有我们需要计算的$3$的次方,而这些次方都只用一次,因此可以从低次往高次算,不保留中间结果。
-
因此,算法流程如下:
- 将
result
初始化为1
,底数为base
,幂为e
,如果幂是负数的话将其取反,最后结果取倒数; - 如果
e & 1 == 1
的话,说明幂的末位为1
,需要计算这个次方,就让result *= base
; - 每次循环都让
base *= base
,即平方,也就是$base^{(2^{k})}$里面的$k$不断增加,如果base
确定为整数的话也可以用左移; -
e >>= 1
,即幂右移1位,也可以用除以2实现,下一次循环就判断下一个$base^{(2^{k})}$需不需要乘到结果里面(步骤2)。 -
e
为0的时候循环结束
- 将
-
伪代码如下(C++代码更好理解):
POWER_INTEGER(x, n) # x^n pow ← 1 while (n > 0) do if (n mod 2 = 1) # mod表示取模,即取余数 then pow ← pow * x x ← x * x n ← n / 2 return pow
-
C++代码如下:
NumberType optimized_pow_n(NumberType x, unsigned int n) { NumberType pw = 1; while (n > 0) { if (n & 1) // n & 1 等价于 (n % 2) == 1 pw *= x; x *= x; n >>= 1; // n >>= 1 等价于 n /= 2 } return pw; }
- 方法一,笨办法,累乘
class Solution {
public:
double Power(double base, int exponent) {
if(exponent == 0){
return 1.;
}
if(base == 0){
return 0.;
}
double result = base;
bool flip_flag = false;
if(exponent < 0) {
flip_flag = true;
exponent = -exponent;
}
while(--exponent) result *= base;
if(flip_flag) result = 1/result;
return result;
}
};
- 方法二,快速幂算法
class Solution {
public:
double Power(double base, int exponent) {
if(exponent == 0){
return 1.;
}
if(base == 0){
return 0.;
}
bool flip_flag = false;
if(exponent < 0) {
flip_flag = true;
exponent = -exponent;
}
double result = 1;
while(exponent){
if(exponent&1){
result *= base;
}
base *= base;
exponent >>= 1;
}
return flip_flag ? 1/result : result;
}
};
网上其他人写的简单版代码
class Solution {
public:
double Power(double base, int exponent) {
long long p = abs( (long long) exponent);
double r = 1.0;
while (p) {
if (p & 1)
r *= base;
base *= base;
p >>= 1;
}
return ( exponent > 0 ) ? r : 1/r;
}
};