题干:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
思路:
本题只要不要忘记这个次数可正可负,就是一道无敌简单的题目。下面首先给出常规做法,即分exponent的正负情况进行累乘即可。
public class Solution {
public double Power(double base, int exponent) {
double sum = 1;
if(exponent>=0){
for(int i=0;i<exponent;i++){
sum=sum*base;
}
}
else {
for(int i=0;i<-exponent;i++){
sum=sum*base;
}
sum=1/sum;
}
return sum;
}
}
然而这只是一种非常常规的做法,在exponent很大的时候,显然不够高效。我们试着分析一下,在计算n次方时,其实有很多可以讨巧的地方。譬如8次方可以用4次方的平方来表示,而4次方又可以用平方的平方来表示。而累乘中却忽视了这一点,只是无脑的从小累乘到大,在数据比较大的时候显然是不够高效的。进一步给出分析如下:
从而得到最终的代码:
public static double Power1(double base, int exponent){
boolean flag = true;//设置标志位,根据标志位输出倒数或者原数
if(exponent<0){//负数无法用右移1位实现除以2,所以所有的负数全部转为正数
flag=false;
exponent=-exponent;
}
double res = unitpower(base,exponent);
return flag ? res : 1/res;
}
public static double unitpower(double base, int exponent){
if(exponent==1){
return base;
}
if(exponent==0){
return 1;
}
double res = unitpower(base,exponent >> 1);//每次递归将exponent除以2
res *=res; //exponent为偶数
if((exponent & 1)==1){//exponent为奇数,同样我们可以用正数&1的值来判断奇数偶数
res *=base;
}
return res;
}
值得一提的是,为了进一步去简化整个代码,用位计算代替了除以2和取余判断奇偶,因为位运算比加减乘数取余的效率高的多。