計算 a^n (n 為非負整數) 是經典演算法題。暴力循環 O(n) 在大指數下極慢,快速冪 (Exponentiation by Squaring) 利用 a^n = (a^(n/2))^2 特性,配合位運算將複雜度降為 O(log n)。本文從數學推導到 Java 實現完整解析。
n 為偶數:a^n = a^(n/2) * a^(n/2)
n 為奇數:a^n = a^((n-1)/2) * a^((n-1)/2) * a
遞歸基準:n=0 → 1、n=1 → a
| 算術運算 | 位運算 | 說明 |
|---|---|---|
n / 2 | n >> 1 | 右移 1 位 = 除以 2 |
n % 2 == 1 | (n & 1) == 1 | 最低位為 1 = 奇數 |
public class FastPower {
/**
* 計算 base^exponent (exponent >= 0)
* 時間複雜度 O(log n),空間複雜度 O(log n) 遞歸棧
*/
public static double power(double base, int exponent) {
if (exponent == 0) return 1;
if (exponent == 1) return base;
// 遞歸計算 base^(exponent/2)
double half = power(base, exponent >> 1); // exponent / 2
double result = half * half; // 平方
// 若指數為奇數,再乘一次 base
if ((exponent & 1) == 1) { // exponent % 2 == 1
result *= base;
}
return result;
}
// 測試
public static void main(String[] args) {
System.out.println(power(5.5, 5)); // 5032.84375
System.out.println(power(2, 10)); // 1024.0
System.out.println(power(3, 0)); // 1.0
}
}
public static double powerIterative(double base, int exponent) {
double result = 1;
double current = base;
int exp = exponent;
while (exp > 0) {
if ((exp & 1) == 1) { // 當前位為 1
result *= current; // 累乘
}
current *= current; // 平方:base^(2^i)
exp >>= 1; // 右移處理下一位
}
return result;
}
迭代邏輯:將指數拆解為二進位,exp=13 (1101b) → base^1 * base^4 * base^8。
// 負指數
public static double power(double base, int exponent) {
if (exponent < 0) return 1 / power(base, -exponent);
// ... 原邏輯
}
// 模冪 (a^b % mod) - 密碼學核心
public static long modPow(long base, long exponent, long mod) {
long result = 1 % mod;
base %= mod;
while (exponent > 0) {
if ((exponent & 1) == 1) result = (result * base) % mod;
base = (base * base) % mod;
exponent >>= 1;
}
return result;
}
| 方法 | 時間複雜度 | 實測耗時 (ms) |
|---|---|---|
| 暴力循環 | O(n) | ~3,000,000 (無法完成) |
| 遞歸快速冪 | O(log n) | ~0.02 |
| 迭代快速冪 | O(log n) | ~0.01 |
a^n = (a^(n/2))^2 * (n%2==1 ? a : 1)/2 → >>1、%2 → &1,CPU 指令級優化