[Python3 練習] 008 歐幾裏德算法
題目:寫個“歐幾裏德算法”的小程序
(1) 描述
- 我知識淺薄,一開始被“歐幾裏德”的大名唬住了,去搜了一下才知道這就是高中時學過的“輾轉相除法”
- 輾轉相除法的用處
- 求兩個正整數的最大公約數
- 示例
- a = 30,b = 18,求 a 與 b 的最大公約數
- a % b = 12 => a = 18, b = 12
- a % b = 6 => a = 12, b = 6
- a % b = 0 => 此時的 b 即為原來兩數的最大公約數
- a = 30,b = 18,求 a 與 b 的最大公約數
- 總結
- 大的數 num1 對小的數 num2 取余
- 把 num2 的值賦給 num1,把余數賦給 num2,再進行上一步操作,直到余數為 0
- 余數為 0 的那個式子中的 num2 即為最大公約數
(2) 證明
- 方法來自互聯網
1) 證明方法1
設 num1,num2,m,r,d 均為自然數
不妨設 num1 > num2,d 為兩個數的任意一個公約數;m 表示倍數,r 表示余數
num1 = m * num2 + r
=> r = num1 - m * num2
等式兩邊同除以 d,得 r/d = (num1 - m * num2)/d = num1/d - m * num2/d
因為 d 為 num1,num2 的公約數,且 m 為自然數
所以 r/d 也是自然數
=> d 必是 r 的約數
=> 求 num1 與 num2 的最大公約數,可以轉為求 num2 與 r 的最大公約數
2) 證明方法2
令 d 為 num1,num2 的最大公約數
取 num1 的某一個約數 m1,num2 的某一個約數 m2,使得 num1 = m1 * d,num2 = m2 * d —— (1)
不妨設 r = num1 % num2 = num1 - m * num2 —— (2)
將 (1) 代入 (2),得 r = m1 * d - m * (m2 * d) = (m1 - m * m2) * d
=> d 也是余數 r 的約數
若 (m1 - m * m2) 與 m2 不互質
不妨設 (m1 - m * m2) = k1 * d‘,m2 = k2 * d‘,(d‘>1)
m1 = m * m2 + k1 * d‘ = m * (k2 * d‘) + k1 * d‘ = (m * k2 + k1) * d‘
=> num1 = m1 * d = [(m * k2 + k1) * d‘] * d = (m * k2 + k1) * (d‘ * d)
? num2 = m2 * d = (k2 * d‘) * d = k2 * (d‘ * d)
=> num1 與 num2 有公約數 (d‘ * d)
因為 d‘ > 1,d >= 1
所以 (d‘ * d) > d
=> 與題設矛盾
=> (m1 - m * m2) 與 m2 互質
=> d 也是 num2 與 r 的最大公約數
(3) 要求
- 寫出“歐幾裏德算法”的程序,起名為 gcd()
- gcd 為 Greatest Common Divisor(最大公約數) 的縮寫
(3) 程序
1) 代碼
# 解法1
def gcd(num1, num2): # 不需要規定 x > y,就算 x < y,取一次余就換回來了
while num2 != 0:
t = num1 % num2
num1 = num2
num2 = t
return num1
# 解法2 更貼近算法的描述
def gcd(num1, num2):
while num1:
num1, num2 = num2 % num1, num1
return num2
2) 運行情況
>>> print(gcd(16, 36))
4
[Python3 練習] 008 歐幾裏德算法