深入理解辗转相除法

辗转相除法求最大公约数


如何理解辗转相除法

(一)可公度线段
Euclid ,中文译作“欧几里得”,古希腊数学家。他用公理化系统的方法归纳整理了当时的几何理论,并写成了伟大的数学著作《几何原本》,因而被后人称作“几何学之父”。
有趣的是,《几何原本》一书里并不全讲的几何。全书共有十三卷,第七卷到第十卷所讨论的实际上是数论问题——只不过是以几何的方式来描述的。
在《几何原本》中,数的大小用线段的长度来表示,越长的线段就表示越大的数。很多数字与数字之间的简单关系,在《几何原本》中都有对应的几何语言。
例如,若数字 a 是数字 b 的整倍数,在《几何原本》中就表达为,长度为 a 的线段可以用长度为 b 的线段来度量。比方说,黑板的长度是 2.7 米,一支铅笔的长度是 18 厘米,你会发现黑板的长度正好等于 15 个铅笔的长度。
我们就说,铅笔的长度可以用来度量黑板的长度。如果一张课桌的长度是 117 厘米,那么 6 个铅笔的长度不够课桌长, 7 个铅笔的长度又超过了课桌长,因而我们就无法用铅笔来度量课桌的长度了。
哦,当然,实际上课桌长相当于 6.5 个铅笔长,但是铅笔上又没有刻度,我们用铅笔来度量课桌时,怎么知道最终结果是 6.5 个铅笔长呢?因而,只有 a 恰好是 b 的整数倍时,我们才说 b 可以度量 a 。
给定两条长度不同的线段 a 和 b ,如果能够找到第三条线段 c ,它既可以度量 a ,又可以度量 b ,我们就说 a 和 b 是可公度的( commensurable ,也叫做可通约的), c 就是 a 和 b 的一个公度单位。
举个例子: 1 英寸和 1 厘米是可公度的吗?历史上,英寸和厘米的换算关系不断在变,但现在,英寸已经有了一个明确的定义: 1 英寸精确地等于 2.54 厘米。
因此,我们可以把 0.2 毫米当作单位长度,它就可以同时用于度量 1 英寸和 1 厘米: 1 英寸将正好等于 127 个单位长度, 1 厘米将正好等于 50 个单位长度。
实际上, 0.1 毫米、 0.04 毫米 、 (0.2 / 3) 毫米也都可以用作 1 英寸和 1 厘米的公度单位,不过 0.2 毫米是最大的公度单位。
等等,我们怎么知道 0.2 毫米是最大的公度单位?更一般地,任意给定两条线段后,我们怎么求出这两条线段的最大公度单位呢?在《几何原本》第七卷的命题 2 当中, Euclid 给出了一种求最大公度单位的通用算法,这就是后来所说的 Euclid 算法。
这种方法其实非常直观。假如我们要求线段 a 和线段 b 的最大公度单位,不妨假设 a 比 b 更长。如果 b 正好能度量 a ,那么考虑到 b 当然也能度量它自身,因而 b 就是 a 和 b 的一个公度单位;
如果 b 不能度量 a ,这说明 a 的长度等于 b 的某个整倍数,再加上一个零头。我们不妨把这个零头的长度记作 c 。
如果有某条线段能够同时度量 b 和 c ,那么它显然也就能度量 a 。也就是说,为了找到 a 和 b 的公度单位,我们只需要去寻找 b 和 c 的公度单位即可。怎样找呢?
我们故技重施,看看 c 是否能正好度量 b 。如果 c 正好能度量 b ,c 就是 b 和 c 的公度单位,从而也就是 a 和 b 的公度单位;如果 c 不能度量 b ,那看一看 b 被 c 度量之后剩余的零头,把它记作 d ,然后继续用 d 度量 c ,并不断这样继续下去,直到某一步没有零头了为止。
我们还是来看一个实际的例子吧。让我们试着找出 690 和 2202 的公度单位。显然, 1 是它们的一个公度单位, 2 也是它们的一个公度单位。我们希望用 Euclid 的算法求出它们的最大公度单位。
首先,用 690 去度量 2202 ,结果发现 3 个 690 等于 2070 ,度量 2202 时会有一个大小为 132 的零头。接下来,我们用 132 去度量 690 ,这将会产生一个 690 – 132 × 5 = 30 的零头。
用 30 去度量 132 ,仍然会有一个大小为 132 – 30 × 4 = 12 零头。再用 12 去度量 30 ,零头为 30 – 12 × 2 = 6 。最后,我们用 6 去度量 12 ,你会发现这回终于没有零头了。
因此, 6 就是 6 和 12 的一个公度单位,从而是 12 和 30 的公度单位,从而是 30 和 132 的公度单位,从而是 132 和 690 的公度单位,从而是 690 和 2202 的公度单位。
我们不妨把 Euclid 算法对 a 和 b 进行这番折腾后得到的结果记作 x 。从上面的描述中我们看出, x 确实是 a 和 b 的公度单位。不过,它为什么一定是最大的公度单位呢?
为了说明这一点,下面我们来证明,事实上, a 和 b 的任意一个公度单位一定能够度量 x ,从而不会超过 x 。如果某条长为 y 的线段能同时度量 a 和 b ,那么注意到,它能度量 b 就意味着它能度量 b 的任意整倍数,要想让它也能度量 a 的话,只须而且必须让它能够度量 c 。
于是, y 也就能够同时度量 b 和 c ,根据同样的道理,这又可以推出 y 一定能度量 d ……因此,最后你会发现, y 一定能度量 x 。
用现在的话来讲,求两条线段的最大公度单位,实际上就是求两个数的最大公约数——最大的能同时整除这两个数的数。
用现在的话来描述 Euclid 算法也会简明得多:假设刚开始的两个数是 a 和 b ,其中 a > b ,那么把 a 除以 b 的余数记作 c ,把 b 除以 c 的余数记作 d ,c 除以 d 余 e , d 除以 e 余 f ,等等等等,不断拿上一步的除数去除以上一步的余数。
直到某一次除法余数为 0 了,那么此时的除数就是最终结果。因此, Euclid 算法又有一个形象的名字,叫做“辗转相除法”。


原文链接:跨越前年的RSA算法


问题的算法描述

  • 不妨令a>b
  • if(a%b==0)—–则表明,这里的b即为所求的最大公约数
  • else b = a%b; a = b; a%b的余数再次和b进行运算,不同的是这里的较大数变成了b

代码实现

int gcd(int a, int b) {
    if (a%b == 0) {
        return b;
    }
    else {
        return gcd(b, a%b);
    }
}

githb原文链接

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值