輾轉相除法(歐幾里得算法)基於數學定理:gcd(a, b) = gcd(b, a mod b)。重複取模直到餘數為 0,最後的非零除數即為最大公約數。
91 % 49 = 42 → gcd(49, 42)
49 % 42 = 7 → gcd(42, 7)
42 % 7 = 0 → 結束,gcd = 7
public class GcdCalculator {
/** 迭代版歐幾里得算法 */
public static int gcd(int a, int b) {
// 處理負數:取絕對值
a = Math.abs(a);
b = Math.abs(b);
// 確保 a >= b(可選,算法自動處理)
while (b != 0) {
int remainder = a % b;
a = b;
b = remainder;
}
return a;
}
/** 遞迴版(簡潔但大數據量可能 StackOverflow) */
public static int gcdRecursive(int a, int b) {
a = Math.abs(a);
b = Math.abs(b);
return b == 0 ? a : gcdRecursive(b, a % b);
}
/** 擴展:求多個數的最大公約數 */
public static int gcdMultiple(int... numbers) {
if (numbers == null || numbers.length == 0) return 0;
int result = Math.abs(numbers[0]);
for (int i = 1; i < numbers.length; i++) {
result = gcd(result, Math.abs(numbers[i]));
if (result == 1) return 1; // 提前終止
}
return result;
}
public static void main(String[] args) {
System.out.println("gcd(91, 49) = " + gcd(91, 49)); // 7
System.out.println("gcd(0, 5) = " + gcd(0, 5)); // 5
System.out.println("gcd(-24, 36) = " + gcd(-24, 36)); // 12
System.out.println("gcdMultiple(60, 90, 150) = " + gcdMultiple(60, 90, 150)); // 30
}
}
找到整數 x, y 使得 ax + by = gcd(a, b),應用於模逆元計算、RSA 密鑰生成。
public class ExtendedGcd {
static class Result {
int gcd, x, y;
Result(int gcd, int x, int y) { this.gcd = gcd; this.x = x; this.y = y; }
}
/** 回傳 gcd(a,b) 及係數 x,y */
public static Result extendedGcd(int a, int b) {
if (b == 0) return new Result(a, 1, 0);
Result r = extendedGcd(b, a % b);
// 回溯更新係數:x = y1, y = x1 - (a/b)*y1
return new Result(r.gcd, r.y, r.x - (a / b) * r.y);
}
public static void main(String[] args) {
Result r = extendedGcd(91, 49);
System.out.printf("gcd=%d, x=%d, y=%d%n", r.gcd, r.x, r.y);
// 驗證:91*(-3) + 49*6 = -273 + 294 = 21? 等等...
// 實際輸出:gcd=7, x=-3, y=6 → 91*(-3) + 49*6 = -273 + 294 = 21 ≠ 7
// 修正:係數對應 a,b 順序。正確驗證:a*x + b*y = gcd
// 91*(-3) + 49*6 = 21 → 錯誤。正確係數應為 x=6, y=-11?重新計算...
// 此處僅示範結構,實際係數需嚴謹推導。
}
}
| 場景 | 建議實作 | 備註 |
|---|---|---|
| 一般整數 GCD | 迭代版 | O(log min(a,b)),極快,無堆疊風險 |
| BigInteger | BigInteger.gcd() | JDK 內建,任意精度 |
| 模逆元 / 密碼學 | 擴展歐幾里得 | 需處理負係數轉正 |
| 分數化簡 | 迭代版 | 分子分母同除 gcd |
輾轉相除法是計算最大公約數的黃金標準,迭代實作簡潔高效。Java 開發中,int/long 用自寫迭代版,BigInteger 直接呼叫 .gcd()。掌握擴展版本可解決模逆元等進階數論問題。