算法的原理:
對於輾轉相除法:i和j的最大公約數,也就是i和j都能夠除斷它。換句話講,就是i比j的n倍多的那個數k(i = j*n + k,即i % j = k)應該也是最大公約數的倍數。所以就能轉換成求k和j的最大公約數。同理,對於更相減損術,同樣的道理,i比j大的部分也是最大公約數的倍數。
代碼:

1 /** 2 * 求最大公約數算法匯總 3 * 4 */ 5 public class GCD { 6 public static void main(String[] args) { 7 GCD gcd = new GCD(); 8 gcd.gcd1(43, 45); 9 gcd.gcd2(64, 80); 10 gcd.gcd3(45, 81); 11 } 12 13 14 /** 15 * 第三種方法:更相減損術 + 輾轉相除法,即 16 * 當a和b均為偶數,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1) 17 * 當a為偶數,b為奇數,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b) 18 * 當a為奇數,b為偶數,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1) 19 * 當a和b均為奇數,利用更相減損術運算一次,gcb(a,b) = gcb(b, a-b), 此時a-b必然是偶數,又可以繼續進行移位運算。 20 */ 21 private void gcd3(int i, int j) { 22 System.out.println("The greatest common divisor is:" + doubleGcd(i, j)); 23 } 24 25 private int doubleGcd(int i, int j) { 26 if (i % j == 0) { 27 return j; 28 } 29 30 if ((i&1) == 0 && (j&1) == 0) { 31 // 都是偶數 32 return doubleGcd(i >> 1, j >> 1) << 1; 33 } else if ((i&1) == 0 && (j&1) != 0) { 34 // i為偶數,j為奇數 35 return doubleGcd(i >> 1, j); 36 } else if ((i&1) != 0 && (j&1) == 0) { 37 // i為奇數,j為偶數 38 return doubleGcd(i, j >> 1); 39 } else { 40 // i和j都為奇數 41 return doubleGcd(i, i > j ? i - j : j - i); 42 } 43 } 44 45 46 /** 47 * 第二種方法:九章算術的更相減損術,即如果i>j,那么先用i-j得到其差k.然后將問題轉換成求k和m的最大公約數.依此類推,直到差為0. 48 * 這個方法也有一個問題,就是如果i和j想差的比較大,那么這個方法存在較高的時間復雜度. 49 */ 50 private void gcd2(int i, int j) { 51 if (i < j) { 52 gcd2(j, i); 53 return; 54 } 55 56 int k = i - j; 57 if (k == 0) { 58 System.out.println("The greatest common divisor is:" + j); 59 return; 60 } else { 61 if (k >= j) { 62 gcd2(k, j); 63 } else { 64 gcd2(j, k); 65 } 66 } 67 } 68 69 /** 70 * 第一種方法:輾轉相除法, 即如果i>j, 那么先用i%j得到余數k.將問題轉換成求k和m的最大公約數.依此類推,直到余數為0. 71 * 該方法有一個比較大的問題問題是取模的性能。 72 */ 73 private void gcd1(int i, int j) { 74 // 確保n>m 75 if (i < j) { 76 gcd1(j, i); 77 return; 78 } 79 80 int k = i%j; 81 if (k == 0) { 82 System.out.println("The greatest common divisor is:" + j); 83 return; 84 } else { 85 if (k >= j) { 86 gcd1(k, j); 87 } else { 88 gcd1(j, k); 89 } 90 } 91 } 92 }