题目描述比较简单,就是求-100.0到100.0的n次幂,n为32位有符号整数。
比如求2.00000的10次幂,则需要返回的值为1024.00000;诶,1024刚过:(
- 首先比较无脑的就是一次次的去累积乘,乘n次,思维很清晰,想法很危险。
- 32位有符号整数,[﹣231,231﹣1],即[﹣2147483648,2147483647]这个范围,我没有试过这种方法,但是看评论有人说这个会报超时。20多亿次乘积运算,有点伤。
- 然后就是大家比较认可的二分递归运算,思路也很清晰,将n一份为二,一直分到n=1或者﹣1。
代码示例:
public double myPow2(double x, int n) {
if (n == 0) { return 1; }
if (n == 1) { return x; }
if (n == -1) { return 1 / x; }
double half = myPow(x, n / 2);
double rest = myPow(x, n % 2);
double total = rest * half * half;
return total;
}
- 其实在二分递归之前,我想到的是将n拆成一个个2的n次幂的和,即xn=xn1+n2+n3+n4+…=xn1*xn2*xn3xn4……,比如10次方,10=2+8,就可计算x的2次方和8次方,再将两个结果乘起来。当然你可能会觉得计算2次方和8次方的过程有重复运算,其实想象成2进制右移运算,或者/2运算的话,可以避免这个重复。
先看下面的代码:
public double myPow(double x, int n) {
long num = n;
if (num < 0) {
x = 1 / x;
num = -num;
}
//最后需要返回的结果,过程中需要累积乘多个x的n1、n2、n3……次幂
double result = 1;
//记录当前位代表的幂级值
double currentMagnification = x;
for (long i = num; i > 0; i >>= 1) {
if ((i % 2) == 1) {
result = result * currentMagnification;
}
currentMagnification = currentMagnification * currentMagnification;
}
return result;
}
为了更方便理解,以上面计算2的10次幂为栗子说明一下。
10的2进制表示为1010,前面省略了28个0。
第0次循环:i=10,即1010,result=1,currentMagnification=21=2;
第一次循环,i=5,即0101,result=1,currentMagnification=22=4;
第二次循环,i=2,即0010,result=14=4,currentMagnification=24=16;
第三次循环,i=1,即0001,result=4,currentMagnification=28=256;
第四次循环,i=0,即0000,result=4256=1024,currentMagnification=216=65536;
循环结束。
这里其实还有一个需要特别注意的地方:long num = n;
这一句并非可有可无,如果省略将n转换为long类型这样一个过程,那么当n=Integer.MIN_VALUE = -2147483648 时,程序运行结果会有异常。2147483648并不是int类型,已经超过了这个范围了。
int num= ﹣(﹣2147483648) = ﹣2147483648
或者
int num = Math.abs(﹣2147483648)= ﹣2147483648