題目描述
給定一個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;
}