輾轉相除法
簡單證明輾轉相除法的原理
1.解析:
8251=6105+2146,為了表示簡單,我就用a=b+c表示這個吧
於是有c=a-b
那么如果有d|a,且d|b,就必然有d|a-b,也就是d|c,
(d|a表示:d為a的約數)
可見a和b的公約數必然也是c的約數.
現在假設d是a和b的最大公約數,那么d也必然是c的約數,於是d是b,c的公約數,現在就要證明它是最大公約數:
2.證明:
因為a=b+c,於是b,c的公約數也必然是a的約數,假設(b,c)=e,
((b,c)=e表示e為b和c的最大公約數)那么有e|b+c,即e|a
根據"d是b,c的公約數"知道d|e,,
又因為e也是a,b的公約數,e|d,綜上有e=d
可見(a,b)=(b,c)=d
(這個思想一推廣,就成了輾轉相除法了)
3.實現
def euclidean_algorithm(a,b): """輾轉相除法求最大公約數""" if a < b: a, b = b, a r = 1 while r != 0: r = a % b a = b b = r return a
《九章算術》更相減損術
思想
可半者半之,不可半者,副置分母、子之數,以少減多,更相減損,求其等也。以等數約之。
白話文譯文:
(如果需要對分數進行約分,那么)可以折半的話,就折半(也就是用2來約分)。如果不可以折半的話,那么就比較分母和分子的大小,用大數減去小數,互相減來減去,一直到減數與差相等為止,用這個相等的數字來約分。
使用步驟
第一步:任意給定兩個正整數;判斷它們是否都是偶數。若是,則用2約簡;若不是則執行第二步。
第二步:以較大的數減較小的數,接着把所得的差與較小的數比較,並以大數減小數。繼續這個操作,直到所得的減數和差相等為止。
則第一步中約掉的若干個2與第二步中等數的乘積就是所求的最大公約數。
其中所說的“等數”,就是
最大公約數。求“等數”的辦法是“更相減損”法。
實現
def gengxianjiansun(a, b): """《九章算術》中的“更相減損術”""" if a < b: a, b = b, a # 初始化差的集合為空 divisors = [] # 初始化最大公約數為1 num = 1 # 第一步:判斷是否都是偶數 if a % 2 == 0 and b % 2 == 0: a, b = a/2, b/2 num *= 2 # 第二步:更替相減 r = a - b while r not in divisors: divisors.append(r) a = max(b, r) b = min(b, r) r = a - b return num * r
附完整代碼
# -*- coding:utf-8 -*- def euclidean_algorithm(a,b): """輾轉相除法求最大公約數""" if a < b: a, b = b, a r = 1 while r != 0: r = a % b a = b b = r return a def gengxianjiansun(a, b): """《九章算術》中的“更相減損術”""" if a < b: a, b = b, a # 初始化差的集合為空 divisors = [] # 初始化最大公約數為1 num = 1 # 第一步:判斷是否都是偶數 if a % 2 == 0 and b % 2 == 0: a, b = a/2, b/2 num *= 2 # 第二步:更替相減 r = a - b while r not in divisors: divisors.append(r) a = max(b, r) b = min(b, r) r = a - b return num * r if __name__ == "__main__": print euclidean_algorithm(8,9) print gengxianjiansun(8,20)