歐幾里得算法


  • 歐幾里得算法

  在數學中,輾轉相除法,又稱歐幾里得算法(英語:Euclidean algorithm),是求最大公約數的算法。兩個數的最大公約數就是能夠同時整除他們的最大正整數。輾轉相除法基於如下原理:兩個整數的最大公約數等於其中較小的數和兩數相除余數的最大公約數。例如,252和105的最大公約數是21(252 = 21 x 12; 105 = 21 x 5 );因為 252 − 105 = 21 × (12 − 5) = 147 ,所以147和105的最大公約數也是21。在這個過程中,較大的數縮小了,所以繼續進行同樣的計算可以不斷縮小這兩個數直至余數為零。這時,所剩下的還沒有變成零的數就是兩數的最大公約數。由輾轉相除法也可以推出,兩數的最大公約數可以用兩數的整數倍相加來表示,如 21 = 5 × 105 + (−2) × 252 。這個重要的結論叫做裴蜀定理。

  兩個數的最大公約數通常寫成GCD(a, b)。如果GCD(a, b) = 1,則稱a和b互素。令g = GCD(a, b)。由於a和b都是g的整數倍,所以可以寫成a = mg、b = ng,並且不存在更大的整數G > g使等式成立。為了使g盡可能大,就要使a和b中所有公約數都提取出來歸入g中,所以自然數m和n一定互素,並且a和b的最大公約數g可以被a和b的所有其他公因數c整除。

  三個數的最大公約數的定義和兩個數的相同,即是它們共有的素因數的積,它們或者也可以按下式計算:

  GCD(abc) = GCD(a, GCD(bc)) = GCD(GCD(ab), c) = GCD(GCD(ac), b).

所以,歐幾里得的輾轉相除法實際可以計算任意多整數的最大公約數。

  • 輾轉相除法計算過程

  輾轉相除法是一種遞歸算法,每一步計算的輸出值就是下一步計算時的輸入值。設k表示步驟數(從0開始計數),算法的計算過程如下:

  每一步的輸入是都是前兩次計算的非負余數rk−1rk−2。因為每一步計算出的余數都在不斷減小,所以,rk−1小於rk−2。在第k步中,算法計算出滿足以下等式的商qk和余數 rk

rk−2 = qk rk−1 + rk

其中0 ≤ rk < rk−1。也就是rk−2要不斷減去rk−1直到比rk−1小。

為求簡明,以下只說明如何求兩個非負整數ab的最大公約數(負數的情況是簡單的)。在第一步計算時(k = 0),設r−2r−1分別等於ab,第2步(此時k = 1)時計算r−1(即b)和r0(第一步計算產生的余數)相除產生的商和余數,以此類推。整個算法可以用如下等式表示: a = q0 b + r0

b =  q 1  r 0 +  r 1
r 0 =  q 2  r 1 +  r 2
r 1 =  q 3  r 2 +  r 3

如果有a < b,算法的第一步實際上會把兩個數字交換,因為這時a除以b所得的商q0會等於0,余數r0則等於a。然后,算法的第二步便是把b除以a,再計算所得之商和余數。所以,對於k ≥ 0總有rk<rk−1,即運算的每一步中得出的余數一定小於上一步計算的余數。

由於每一步的余數都在減小並且不為負數,必然存在第N步時rN等於0,使算法終止,rN−1就是ab的最大公約數。其中N不可能無窮大,因為在r0和0之間只有有限個自然數。 

  • 輾轉相除法計算機實現

  Rust實現:

 1 fn gcd(x: isize, y: isize) -> Option<isize> {
 2     match (x,y) {
 3         (0, 0)         => None,
 4         (a, 0)         => Some(a.abs()),
 5         (mut a, mut b) => { 
 6             while b != 0 {
 7                 let t = b;
 8                 b = a % b;
 9                 a = t;
10             }
11 
12             Some(a.abs()) 
13         },
14     }
15 }

 Rust測試代碼:

1     #[test]
2     fn gcd_works() {
3         assert_eq!(gcd(3,4), Some(1));
4         assert_eq!(gcd(10,5), Some(5));
5         assert_eq!(gcd(1005,50), Some(5));
6         assert_eq!(gcd(99977,777), Some(1));
7     }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM