1. 程式人生 > 其它 >技術實踐第二期|Flutter異常捕獲

技術實踐第二期|Flutter異常捕獲

輾轉相減法和輾轉相除法。

最大公約數是個很常用的概念,例如9和6的最大公約數是3,記作 gcd(9, 6) = 3 ,最小公倍數則為 6×9 mod gcd(6, 9) 。

我們知道,含有兩個未知數的二元一次方程可以表示成平面直角座標系內的一條直線,當擁有兩條相交直線我們通過代入消元可以得到唯一解,而只有一條直線時,則有無數個 (x, y) 座標滿足等式。

而針對這樣一個方程 ax+by = m ,貝祖定理告訴我們,當該方程有整數解時,當且僅當 m 是 a 和 b 的最大公約數的倍數,可以表示成 ax+by = gcd(a, b)*k (K∈Z) ,例如 9x+6y = 12 有整數解。特別地,方程 ax+by = 1 有整數解當且僅當 a 和 b 互質,即 gcd(a, b) = 1。這個定理在 RSA 加密演算法中需要用到。

我們首先看兩個數的最大公約數的求法,常用的方法是輾轉相減法(又稱更相減損術)和輾轉相除法(又稱歐幾里得演算法)。

以C語言程式碼的形式展示兩種演算法。

 1 #include <stdio.h>
 2 
 3 int main() {
 4     int a, b,r ;
 5     scanf("%d%d", &a, &b);
 6     
 7     // 輾轉相減法 
 8 //    while(a != b) {
 9 //        a>b ? a-=b : b-=a;
10 //    }
11     
12     // 輾轉相除法
13     r = 1
; 14 while(r) { 15 r = a % b; 16 a = b; 17 b = r; 18 } 19 20 printf("%d", a); 21 return 0; 22 }

輾轉相減法簡單且容易記,每次以大數減小數,當兩數減到相等時即為最大公約數。但效率不及輾轉相除法,例如求 2000000000 與 1 的最大公約數,輾轉相減法需要讓 2000000000 不斷自減一,直到等於 1 ,得到最大公約數 1 ,總共迴圈 2000000000-1 輪;輾轉相除法則只需要一輪就可完成計算。

以下給出求若干正整數的最大公約數的C語言程式碼。

 1
#include <stdio.h> 2 3 #define MAX_LENGTH 3000 4 5 int GCD(int *num, int n); 6 7 /* 8 8 9 26 39 13 65 52 104 78 91 10 */ 11 int main() { 12 int i, j, n, num[MAX_LENGTH], gcd; 13 14 // 1. 資料輸入 15 scanf("%d", &n); 16 for(i=0; i<n; i++) { 17 scanf("%d", &num[i]); 18 } 19 20 // 2. 獲取該批資料的最大公約數 21 gcd = GCD(num, n); 22 printf("%d", gcd); 23 24 return 0; 25 } 26 27 int GCD(int *num, int n) { 28 int i, j, r, gcd=num[0]; 29 30 for(i=1; i<n; i++) { 31 // 輾轉相減法 32 // while(gcd != num[i]) { 33 // gcd>num[i] ? gcd-=num[i] : num[i]-=gcd; 34 // } 35 36 // 輾轉相除法 37 r = 1; 38 while(r) { 39 r = gcd % num[i]; 40 gcd = num[i]; 41 num[i] = r; 42 } 43 } 44 return gcd; 45 }
若干正整數的最大公約數