阅读 277
欧几里得算法原理详解

欧几里得算法原理详解

前言

欧几里得算法又称辗转相除法,用于计算两个非负整数a,b的最大公约数

对于计算最大公约数这个问题来说,可以想到的一种暴力做法为,遍历从1~ min(a,b)之间的每个数,依次判断是否为a,b的公约数,并全局记录一个最大值。其时间复杂度较高,为O(n)

背景

而欧几里得算法能在较短的时间内正确的计算出a,b的最大公约数,首次出现于欧几里得的《几何原本》中

其公式为

gcd(a,b) = gcd(b,a mod b),要求a >= b

gcd即Greatest Common Divisor最大公约数的缩写

该算法不断地将b,a mod b作为新的a,b进行迭代计算

直到当b为0时,此时的a就是最大公约数

示例

我们举个例子来说明:求25,10的最大公约数

按照欧几里得算法需进行以下几个步骤:

  1. 25 / 10 = 2 ... 5 gcd(25,10) = gcd(10,5)
  2. 10 / 5 = 2 ... 0 gcd(10,5) = gcd(5,0)
  3. 此时参数b为0,因此25和10的最大公约数就是5

5确实是25和10的最大公约数,没有问题

且其能快速收敛到b等于0的情况并结束计算,时间复杂度非常低

根据证明,它需要的步骤不会超过较小数的位数(十进制下)的五倍

原理

该算法看似比较简单,只有一行公式。下面本文将介绍其原理,及正确性证明,因为学习算法不仅需要知道算法流程,还需要知道其为什么正确

以下证明过程没有用到复杂的数学公式,尽量做到通俗易懂

一个引理

在数论里面有一个基本的引理:

如果d能整除a,且d能整除b,那么d能整除 (ax + by),其中x,y是a,b的整数系数

该引理其实比较好理解:若果a和b都是d的整数倍,那么a和b的任意倍数的组合,也是d的整数倍

下面是证明过程:若a = md,b = nd,则(ax + by) = (am + bn)d,因为a,m,b,n都是整数,因此am + bn 也是整数,因此该引理成立

该引理非常重要,下面的证明正确性十分依赖该引理!

同一组数

下面证明(a,b)的所有公约数和 (b,a mod b)的所有公约数是同一组数


对于(a,b)的任意公约数d,根据公约数的性质可得:d既是a的约数,也是b的约数。因此d能整除a,d也能整除b

根据引理可得:d能整除 a - cb (系数分别为1,-c)

下面再来看(b,a mod b):a mod b可以看做 a - (a整除b) * b,a整除b我们用c代替

因此a mod b可以写作 a - cb,则(b , a mod b)可以写作 (b,a - cb)

对于(a,b)的任意公约数

  • 其一定能整除 b:由定义得出
  • 也一定能整除a - cb:由引理得出

因此其一定也是(b,a mod b)的公约数


我们再反过来看,对于(b,a mod b)的任意公约数d,根据公约数的性质可得:d既是b的约数,也是a - cb的约数。因此d能整除b,d也能整除a - cb

根据引理可得:d能整除 cb + a - cb (这里将b的系数取为c,a - cb的系数取为1)= a

对于(b,a mod b)的任意公约数

  • 其一定能整除 b:由公约数定义得出
  • 也一定能整除a:由引理得出

因此其一定也是(a,b)的公约数


综合以上两个结论:

  1. 对于(a,b)的任意公约数,其一定也是(b,a mod b)的公约数
  2. 对于(b,a mod b)的任意公约数,其一定也是(a,b)的公约数

可以得出: (a,b)的所有公约数和 (b,a mod b)的所有公约数是同一组数

为什么能得出该结论呢?假设不是同一组数,则一定有些数是(a,b)独有,或(b,a mod b)独有,不管哪种情况,都会违背结论1或结论2,因此其就是同一组数

最大公约数

现在既然公约数都是同一组了,那最大的公约数一定也相同,因此:

(a,b)的最大公约数,等于 (b,a mod b)的最大公约数

迭代末尾

这个迭代不会永远进行下去,很快就会遇到b为0的情况:

(b1,0),b1为大于0的整数

根据之前的推导,原始数据(a,b)的最大公约数,就等于(b1,0)的最大公约数

那么(b1,0)的最大公约数怎么计算呢?

其实就等于b1,因为b1 能整除 b1,同时b1也能整除0,则b1 是(b1,0)的公约数。那是不是最大的呢?

答案为是,因为不可能存在比b1更大的数,作为其公约数了,因此b1就是 (b1,0)及 (a,b)的最大公约数

代码示例

程序代码其实非常简单

private int gcd(int a,int b) {

    return b == 0 ? a : gcd(b,a % b);

}
复制代码

总结

本文介绍了计算两个数的最大公约数的经典算法:欧几里得算法的实现,及正确性证明

文章分类
阅读
文章标签