計算 a^n(n 為非負整數)是經典算法問題。暴力循環乘法時間複雜度 O(n),當 n 極大(如 10^9)時不可接受。本文詳解「快速冪」(Exponentiation by Squaring)算法,將複雜度降至 O(log n),並給出遞歸與迭代兩種 Java 實現,解析位運算優化細節。
利用冪的性質分解指數:
a^n = (a^(n/2))^2a^n = (a^((n-1)/2))^2 × a每步將指數減半,遞歸深度/循環次數為 log₂(n)。
public class FastPower {
public static double power(double base, int exponent) {
if (exponent == 0) return 1;
if (exponent == 1) return base;
double half = power(base, exponent >> 1); // exponent / 2
double result = half * half; // 平方
if ((exponent & 1) == 1) { // 奇數檢查
result *= base;
}
return result;
}
public static void main(String[] args) {
System.out.println(power(5.5, 5)); // 5032.84375
}
}
| 操作 | 等價算術 | 說明 |
|---|---|---|
exponent >> 1 | exponent / 2 | 算術右移一位,丟棄最低位,等同整除 2 |
(exponent & 1) == 1 | exponent % 2 == 1 | 最低位為 1 表示奇數,位與比取模快 |
現代 JVM JIT 編譯器會自動優化 /2 和 %2,但位運算寫法更明確表達意圖,且在嵌入式/底層場景有優勢。
避免遞歸棧溢出,常數空間 O(1):
public static double powerIter(double base, int exponent) {
if (exponent < 0) { // 支持負指數
base = 1 / base;
exponent = -exponent;
}
double result = 1;
while (exponent > 0) {
if ((exponent & 1) == 1) {
result *= base;
}
base *= base;
exponent >>= 1;
}
return result;
}
邏輯:從二進制最低位開始,若該位為 1,累乘當前 base;每輪 base 自乘(平方),指數右移。
竞賽編程/加密常需求,防溢出:
public static long modPow(long a, long n, long mod) {
long res = 1 % mod;
a %= mod;
while (n > 0) {
if ((n & 1) == 1) res = (res * a) % mod;
a = (a * a) % mod;
n >>= 1;
}
return res;
}
Integer.MIN_VALUE 取反溢出,建議用 long 接收BigDecimal 或對數運算BigInteger快速冪是「分治 + 位運算」的經典範例,將 O(n) 降為 O(log n)。掌握遞歸與迭代兩種寫法,理解 >>=1、&1 的本質,能在算法面試、競賽編程、密碼學實現中遊刃有餘。生產代碼推薦迭代版,並根據業務添加邊界檢查與取模邏輯。