在数学中,辗转相除法,又称欧几里得算法(英語:Euclidean algorithm),是求最大公约数的算法。
两个整数的最大公约数是能够同时整除它们的最大的正整数。
辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数。
例如,252
和105
的最大公约数是21
(252=21*12;105=21*5
);因为 252 − 105 = 21 × (12 − 5) = 147
,所以147
和105
的最大公约数也是21
。在这个过程中,252
较大的数缩小变成了147
,但是他们的最大公约数在减法算术中是不会变化的,我们可以利用这个性质,在不知道公约数的情况下,不断缩小除数,所以继续进行同样的计算可以不断缩小这两个数直至其中一个变成零。这时,所剩下的还没有变成零的数就是两数的最大公约数。
由辗转相除法也可以推出,两数的最大公约数可以用两数的整数倍相加来表示,如 21 = 5 × 105 + (−2) × 252
。这个重要的結論叫做貝祖定理。
正确性的证明
辗转相除法的正确性可以分成两步来证明。
- 在第一步,我們會證明算法的最终结果
r
N
−
1
r_{N−1}
rN−1 同时整除
a
和b
。因为它是一个公约数,所以必然小于或者等于最大公约数g
。 - 在第二步,我們證明
g
能整除 r N − 1 r_{N−1} rN−1。所以g
一定小于或等于 r N − 1 r_{N−1} rN−1。 - 两个不等式只在
r
N
−
1
r_{N−1}
rN−1=
g
时同时成立。
具体证明如下:
- 证明 r N − 1 r_{N−1} rN−1同时整除a和b:
- 因为余数
r
N
r_{N}
rN是0,
r
N
−
1
r_{N−1}
rN−1能够整除
r
N
−
2
r_{N−2}
rN−2:
r N − 2 r_{N−2} rN−2= q N q_{N} qN r N − 1 r_{N−1} rN−1 - 因为
r
N
−
1
r_{N−1}
rN−1能够整除
r
N
−
2
r_{N−2}
rN−2,所以也能够整除
r
N
−
3
r_{N−3}
rN−3:
r N − 3 r_{N−3} rN−3 = q N − 1 q_{N-1} qN−1 r N − 2 r_{N−2} rN−2 r N − 3 r_{N−3} rN−3 - 同理可证
r
N
−
1
r_{N−1}
rN−1可以整除所有之前步骤的余数,包括
a
和b
,即 r N − 1 r_{N−1} rN−1是a
和b
的公约数, r N − 1 r_{N−1} rN−1 ≤g
。
- 证明最大公约数g能整除rN-1:
- 根据定义,
a
和b
可以写成g
的倍数:a = mg
、b = ng
,其中m
和n
是自然数。因为 r 0 r_0 r0 = a − q 0 q_0 q0b = mg − q 0 q_0 q0ng = (m − q 0 q_0 q0n)g,所以g
整除 r 0 r_0 r0。同理可证g
整除每个余数 r 1 r_1 r1, r 2 r_2 r2, …, r N − 1 r_{N-1} rN−1。因為最大公约数g
整除 r N − 1 r_{N-1} rN−1,因而g
≤ r N − 1 r_{N-1} rN−1。
因为第一步的证明告诉我们 r N − 1 r_{N-1} rN−1 ≤g
,所以g
= r 0 r_0 r0。即:
g = GCD(a, b) = GCD(b, r 0 r_0 r0) = GCD( r 0 r_0 r0, $r_1) = … = GCD( r N − 2 r_{N-2} rN−2 , r N − 1 r_{N-1} rN−1) = r N − 1 r_{N-1} rN−1
代码实现
迭代版本:
int gcd(int m,int n)
{
int t = 1;
while(t != 0)
{
t=m%n;
m=n;
n=t;
}
return m;
}
递归版本:
int gcd(int n,int m)
{
if(m==0)
return n;
else
return gcd(m,n%m);
}