题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
分析:一看到这个题目,可能我们很容易写出来
public double powerWith(double base, int exponent){
double result = 1.0;
for(int i = 1;i <= exponent;i++){
result *= base;
}
return result;
}
如果按照上面的这么写的话,存在问题,如果输入的指数(exponent)是0和负数的时候怎么办?上面的代码完全没有考虑,只包括了指数为正数的情况。
我们知道当指数为负数的时候,可以先对指数求绝对值,然后算出次方的结果之后再取倒数。既然有求倒数,就要想到有没有可能对0求倒数,如果对0求倒数怎么办?当底数
base是零且指数是负数的时候,发现对0求倒数从而导致程序运行出错。
public class Solution1 {
public double Power(double base, int exponent) {
double result = 0.0;
//当底数为0,指数为负数时,则抛出异常或者返回0.0
if(base == 0 && exponent < 0){
return 0.0;
}
if(exponent < 0){
int absExponent = Math.abs(exponent);
result = powerWith(base, absExponent);
result = 1.0 / result;
}else if(exponent == 0){
return 1.0;
}else{
result = powerWith(base, exponent);
}
return result;
}
//计算数值的整数次方
public double powerWith(double base, int exponent){
double result = 1.0;
for(int i = 1;i <= exponent;i++){
result *= base;
}
return result;
}
public static void main(String[] args) {
Solution1 s = new Solution1();
System.out.println(s.Power(0, 0));
System.out.println(s.Power(0, -1));
System.out.println(s.Power(2, 0));
System.out.println(s.Power(-2, 0));
System.out.println(s.Power(2, 3));
System.out.println(s.Power(2, -3));
}
}
上面的这么写就可以了,但是在效率上不高,可以优化powerWith 函数。
如果输入的指数exponent为32,我们在函数powerWith 的循环中需要做31次乘方。
但我们可以换一种思路考虑:我们的目标是求出一个数字的32次方,如果我们已经知道了它的16次方,那么只要在16次放的基础上再平方一次就可以了。而16次方又是8次方的
平方。
这样以此类推,我们求32次方只需要5次乘方:先求平方,在平方的基础上求4次方,在4次方的基础上求8次方,在8次方的基础上求16次方,最后在16此方的基础上求32次方。
我们可以利用下面这个公示求a的n次方:
优化为:
public double powerWith2(double base, int exponent) {
if(exponent == 0){
return 1;
}
if(exponent == 1){
return base;
}
//exponent >> 1 相当于 exponent/2
double result = powerWith2(base, exponent >> 1);
result *= result;
if (exponent % 2 == 1) {
result *= base;
}
return result;
}