剑指offer—数值的整数次方,LeetCode-50. Pow(x, n)
题目描述
实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
思路
x n = x 2 k 1 + 2 k 2 + . . . 2 k i x^{n}=x^{2^{k_1}+2^{k_2}+...2^{k_i}} xn=x2k1+2k2+...2ki
= x 2 k 1 ∗ x 2 k 2 ∗ . . . ∗ x 2 k i \qquad\qquad\quad\ =x^{2^{k_1}}*x^{2^{k_2}}*...*x^{2^{k_i}} =x2k1∗x2k2∗...∗x2ki
现在还不是那么明显,那么我们举例子看看
x 5 = x 101 = x 2 2 ∗ x 2 0 x^{5}=x^{101}=x^{2^{2}}*x^{2^{0}} x5=x101=x22∗x20
x 11 = x 1011 = x 2 3 ∗ x 2 1 ∗ x 2 0 \qquad x^{11}=x^{1011}=x^{2^{3}}*x^{2^{1}}*x^{2^{0}} x11=x1011=x23∗x21∗x20
假如我们现在求 x 11 x^{11} x11,按照普通的方法我们一直连乘到11,但是这样还是比较慢的,特别是数在比较大的时候,乘法的性能还是很低的。
看上面的式子,我们可以用一个变量保存2的次方值,来表示当前的权重,幂上当前位上是否有值,如果有,就用当前值乘上这个权重值。然后幂在除以2,继续下一位的判断。
代码
double myPow(double x, int n) {
long long N = n; //开long long变量是防止复数刚好在边界上,转换为正数时会报错
if(N < 0)
{
x = 1/x;
N = -N;
}
double result = 1;
double temp = x; //权重值
for (long long i = N; i > 0; i/=2) {
if (i%2 == 1){ //若判断幂上当前位为1,则相乘
result *= temp;
}
temp *= temp; //向左移动,权重值*2
}
return result;
}
假如我们现在求 2 11 2^{11} 211,根据上面的代码,我们有下面的表格
i | 原生数 | 二进制幂 | 权重位是否为1 | result | temp |
---|---|---|---|---|---|
11 | 2 1011 2^{1011} 21011 | 1011 | - | 1 | 2 |
11 | 2 1011 2^{1011} 21011 | 1011 | 是 | 1 ∗ 2 1*2 1∗2 | 2 2 2^{2} 22 |
5 | 2 101 2^{101} 2101 | 101 | 是 | 1 ∗ 2 ∗ 2 2 1*2*2^{2} 1∗2∗22 | 2 4 2^{4} 24 |
2 | 2 10 2^{10} 210 | 10 | 否 | 1 ∗ 2 ∗ 2 2 1*2*2^{2} 1∗2∗22 | 2 8 2^{8} 28 |
1 | 2 1 2^{1} 21 | 1 | 是 | 1 ∗ 2 ∗ 2 2 ∗ 2 8 1*2*2^{2}*2^{8} 1∗2∗22∗28 | 2 16 2^{16} 216 |