歐幾里得算法(代碼及證明過程)
一、基礎知識
歐幾里得算法的原理是 GCD遞歸定理
GCD遞歸定理:
對任意 非負整數 a 和 任意 整數 b,
gcd(a,b) = gcd(b, a mod b)
爲了證明這個定理,我們首先需要知道一下幾個有關 gcd
的基本知識跟相關等式跟推論
1.1 基本知識:
-
公約數
定義:如果
d|a
(d 整除 a)且d|b
,那麼 d 是 a 與 b 的 公約數。性質:如果
d|a
且d|b
,那麼d|(ax + by); x,y ∈ Z(任意整數)
-
最大公約數
定義:兩個非零整數 a 和 b 的公約數裏最大的就是 最大公約數。
1.2 相關等式跟推論:
- 等式 1:如果
a|b 且 b|a
那麼a = ±b
- 等式 2:如果
d|a 且 d|b
那麼d|(ax + by); x,y ∈ Z
- 等式 3:
a mod n = a - n⌊a/n⌋(向下整除); a∈Z,n∈N*(正整數)
- 推論 1:對任意整數 a , b,如果
d|a 且 d|b
則d|gcd(a, b)
二、證明過程
如果我們想要獲得結論gcd(a,b) = gcd(b, a mod b)
那麼我們只需要證明gcd(a,b)|gcd(b, a mod b) 且 gcd(b,a mod b)|gcd(a,b)
就可以利用等式 1來證明他倆相等了。
2.1 證明 gcd(a,b)|gcd(b,a mod b)
設
d = gcd(a, b)
∴
d|a 且 d|b
∵ 由 等式 3 可知:
(a mod b) = a - qb
q = ⌊a/b⌋
∴
a mod b
是 a 與 b 的線性組合∴ 由 等式 2 可知 :
d|(a mod b)
∵
d|b 且 d|(a mod b)
∴ 由 推論 1 可知
d|gcd(b, a mod b)
等價結論:
gcd(a, b)|gcd(b, a mod b)
2.2 證明 gcd(b,a mod b)|gcd(a,b)
設
c = gcd(b, a mod b)
∴
c|b 且 c|(a mod b)
∵
a = qb + r
r = a mod b
q = ⌊a/b⌋
∴ a 是 b 和 (a mod b) 的線性組合
∴ 由 等式 2 可知:
c|a
∵
c|a 且 c|b
∴ 由 推論 1 可知:
c|gcd(a, b)
等價結論:
gcd(b, a mod b)|gcd(a, b)
s
2.3 證明 gcd(a,b) = gcd(b, a mod b)
由 上述兩個結論 可知:
gcd(a, b)|gcd(b, a mod b)
gcd(b, a mod b)|gcd(a, b)
∴ 由 等式 1 可知:
gcd(a, b) = gcd(b, a mod b)
到這裏 GCD遞歸定理 就證明結束了
三、代碼
在這裏我放上幾個常用的獲取 兩個數字GCD的代碼:
-
遞歸:
// 一般形式 int gcd(int a, int b) { if(b == 0) return a; return gcd(b, a % b); }
// 簡化形式 int gcd(int a, int b) { return (b==0) ? a : gcd(b, a % b); }
-
非遞歸:
int gcd(int a, int b) { int tmp; while(b != 0) { tmp = b; b = a % b; a = tmp; } return a; }
-
位運算:
// 一般形式 int gcd(int a, int b) { while(b) { a %= b; // 下面三行是交換 a 跟 b 的值 b ^= a; a ^= b; b ^= a; } return a; }
// 簡化版 int gcd(int a,int b) { while(b^=a^=b^=a%=b); return a; }
四、參考資料
《算法導論 (第三版)》 -- 第31章 數論算法