这是看Problem solving with algorithms and data structures using python这本书时遇到的,干脆查了查。
数学原理参考自:https://www.cnblogs.com/kirito-c/p/6910912.html?utm_source=itdadao&utm_medium=referral
有两个数a和b,其中a不小于b,求两者的最大公约数(greatest common divisor/ gcd),欧几里得算法(辗转相除法)可表示为如下形式:gcd(a,b)=gcd(b, a mod b),其中a mod b表示a除以b得到的余数。这里暂时看不出来明显的“辗转"概念,先证明一下这个式子:
假设a mod b = r,即a除以b得到余数r,则有a=kb+r,其中k是整数,若r不为0。
假设a和b的一个公约数为u,则有a=mu, b=nu,其中m,n都是整数。
则余数r=a-kb=mu-knu=(m-kn)u,其中m-ku也是整数,则该式表示余数r也有约数u。因此a和b的公约数一定也是r的约数,即也是b和两者余数r的公约数。
再设b和r有公约数v,则有b=sv,r=tv,其中s,t都是整数。
则a=kb+r=ksv+tv=(ks+t)v,其中ks+t也是整数,则该式表示a也有公约数v。因此b和r的公约数一定也是a的约数,即也是a和b的公约数。
到此就得到了:a和b的公约数等价于b和余数r的公约数(两者完全一致),因此求a和b的公约数就可转化为求除数b和余数r的公约数。由于a不小于b,这个转化相当于在一步步变小计算量,更为简洁。同时借助这个推论,可以一直进行转换,直到余数为0。
即gcd(a,b)=gcd(b, a mod b)=gcd(a mod b, b mod (a mod b))=......。即不断地求除数和余数间的公约数。当最终余数为0时,即可以整除时,最大公约数就是除数,即a和b的最大公约数,return 除数即可。
python实现:
def gcd(a, b):
if a % b != 0:
r = a % b
b = a
return gcd(b,r)
else:
return b