1、循環傻乘
2、遞歸調用
比如3^5(3的5次冪),利用遞歸每次減半相乘。
/**
* 遞歸
* 例如:我們想求3的8次冪是多少,3^8=?
* 思路:我們可以將問題拆分,轉換爲
* 3^8 = (3^4) * (3^4)
* = (3^2 * 3^2) * (3^2 * 3^2)
* = (3 * 3) * (3 * 3) * (3 * 3) * (3 * 3)
* 偶數:
* f(3,8)
* => f(9, 8/2)
* => f(81, 4/2)
* => f(6561, 2/2)
* => 6561 * f(6561 * 6561, 1/2) 返回
* 奇數:
* f(3,9) 因爲奇數只比偶數多出一個底數。所以減去一個底數按偶數計算,最後把偶數算出來的結果在乘上一個底數即可
* => 3 * f(9, (9-1)/2)
* => f(81, 4/2)
* 其餘與偶數一致....
*
* @param x 底數
* @param n 次冪
* @return 計算結果
*/
public static double powerRecursion(int x, int n) {
// 如果n爲0,則直接返回1。例如:2^0=1;3^0=1依次類推
if (n == 0) {
return 1;
}
// 如果n爲負數,則轉爲倒數。例如:2^-2=1/4;3^-3=1/27以此類推
if (n < 0) {
return 1 / powerRecursion(x, Math.abs(n));
}
// 如果n爲奇數,n%2==1 則爲奇數,或者使用 n&1 == 1 也可以,(n >> 1 << 1) == n 就是看數字的二級制最後一位是否是1
if (n % 2 == 1) {
// 如果是奇數的話
return x * powerRecursion(x * x, (n - 1) / 2);
}
// 偶數
return powerRecursion(x * x, n / 2);
}
3、循環
/**
* 循環
* 如果我們求2^5的話,表示成二級製爲00100000。 2^0<<5向左移動5位 , 00000001 => 00100000
* 00100000 = (0*2^7) + (0*2^6) + (1*2^5) + (0*2^4) + (0*2^3) + (0*2^2) + (0*2^1) + (0*2^0)
* 求3的5次冪 3^5 = ?
* 思路:將3^5進行拆分 3^5 = 3^4 * 3^1
*
* 首先將5轉換成2進制 = 00000101 將二進制拆分成多個2的等次冪。即二進制位只能存在一個1.
* 00000101 = 00000100 + 00000001;
* 怎麼拆分呢?只要判斷二級制末尾是否爲1即可,如果爲1則將結果相乘。 計算完成後,對二進制位再向右位移1位,依次進行。
* .......第4位=>3^16、第3位=>3^8、第2位=>3^4、第1位=>3^2、第0位=>3^1
* 由於5對應的二進制上只有第0、2位上是1,所以將0、2位對應的值相乘。即3^4*3^1
* @param x 底數
* @param n 次冪
* @return 結果
*/
public static double powerLoop(int x, int n) {
// 如果小於0求倒數
if (n < 0) {
x = 1 / x;
n = -n; // n = Math.abs(n)
}
// 聲明結果
double result = 1;
while (n != 0) {
if ((n & 1) != 0) {
result *= x;
}
x *= x;
n >>= 1;
}
return result;
}