依旧先摆出算法代码:
1: int get_common_divisor(int a,int b)
2: {
3: int x=a;
4: int y=b;
5: int m=0;
6:
7: while(y>0)
8: {
9: m=x%y;
10: x=y;
11: y=m;
12: }
13:
14: return x;
15: }
欧几里德求最大公约数的原理为:
计A,B两数最大公约数为Gcd(A,B),则Gcd(A,B)=Gcd(B,A Mod B)=Gcd(A Mode B,B Mod (A Mod B))… 公式(1)
即两数的最大公约等于第二数和两数余数的最大公约,其值为公式(1)循环最后余数为0之前的那次余数值。
现在给出命题:
求证欧几里德求最大公约数的正确性。
证明:
只讨论A>B的情形,因为B>A时将在第一次模运算之后(line 9)将二者位置翻转,仍然变成符合x>y的情形。
一种很明显的情形是A是B的倍数,则B显然是最大公约数,这符合Gcd(A,B)=Gcd(B,0)=B,这里利用了一个定理:任何数都是0的公约数。
现把A与B的求余运算改成形式A=Bk+m,显然此处默认B>m求k>=1. 记为公式(2)
不妨取A,B最大公约数存在且为G.则A,B分别可以写成含最大公约数的因式A=G*T1,B=G*T2; 记为公式(3)
公式(3)代入公式(2),A=Bk+m推导出G*T1=G*T2*k+m, m=G*(T1-T2*k); 显然我们得出一个结论:余数m必然包含最大公约数G,
而每一次循环求余都将导致下一次的余数在不断减小,这是一个必然的事实,而另一个事实是余数若不呗整除则必然是正整数并渐小,而正整数的余数渐小若一直没有被整除则必然趋于1,而1能被任何数整除也是任何数的公约数,如果该减小的余数在某一步被整除了,则这个余数恰是自己和被除数的最大公约数,也即A,B的最大公约数。
不妨另循环求余中所有的余数取值为{m1,m2,…,mk,0},很显然由上述推理mk就是我们所要求的最大公约数。