前言
求两数的最大公约数,一共有四种方法:暴力穷举法、更相减损法、辗转相除法、stein 算法,小女不才,花了几天的时间终于把这几种方法全部弄明白,现在就把它们全部分享出来。
首先,假设被求的两个数为 x、y,且 x > y。最大公约数 d = gcd (x , y)
1.暴力穷举法
正如名字所说,暴击穷举法就是简单粗暴地把 1~ y(前面已经假设 x > y)都列出来分别判断是否为 x、y 的公约数,然后再找到其中最大的一个。
暴力穷举法最大的特点就是简单直接、很容易理解,但是计算比较繁琐。
2.辗转相除法
辗转相除法是由古希腊数学家欧几里得在其著作《The Elements》中提出的,所以辗转相除法又名欧几里得算法。
步骤
假设要用辗转相除法求 36 和 24 的最大公约数,则要经历以下步骤:
36 ÷ 24 = 1 …… 12
24 ÷ 12 = 2 …… 0
12 为 36 和 24 的最大公约数
即
先用 x 除以 y
若余数为 0 则 y 为两数的最大公约数;若余数不为零,则令 x = y,y = 余数,重复步骤 1 直到余数为 0,此时的 y 为两数的最大公约数。
原理
相信从上面的阐述中,大家应该可以发现,辗转相除法依赖于一个定理:
两个整数的最大公约数等于其中较小的那个数和两数取模的最大公约数。
即:gcd (x , y) = gcd (y , x % y ) ,其中 x > y。
证明:
设 d = gcd (x , y);
则 x % d = 0 , y % d = 0 ;
则设 x = a * d , y = b * d ;
余数 r = x % y = (a * d) % (b * d) = d * (a % b);
所以 r % d = 0 ;
即 (x % y) % d = 0;
所以 gcd (x , y) = gcd (y , x % y )
3.更相减损法
更相减损法出自《九章算术》,其原理其实与辗转相除法一样,只是辗转相除法将的是相除取余,而更相减损法讲的是相减取差。
步骤
下面先看实例:(还是求36和24的最大公约数)
36 - 24 = 12
24 - 12 = 12
12 是 36 和 24 的最大公约数
即:
x - y = r
若 r = 0 ,则 x = y ,最大公约数为它本身;若 r ≠ 0,则令 x = y 和 r 中较大的一个数 , y = 剩下的另一个数,重复步骤 1 直到 r = 0,此时的 x = y ,即为最大公约数。
原理
从上面的阐述中,大家应该也能发现,更相减损法的原理依赖于下式:
gcd (x , y) = gcd (y , x % y ) ,其中 x > y。
证明:
d = gcd (x , y);
则 x % d = 0 , y % d = 0;
设 x = a *d , y = b * d;
则 r = x - y = a * d - b * d = d * (a - b);
所以 r % d = 0;
即 (x - y) % d = 0;
所以 gcd (x , y) = gcd (y , x - y);
比较
这里我们可以将更相减损法和辗转相除法进行比较:
将上面两个实例中的式子稍稍变形:
辗转相除法 36 = 24 + 12 ; 24 = 12 * 2
更相减损法 36 = 24 + 12 : 24 = 12 + 12
可以看到,两种方法的本质并无太大差别,从代码上看,两种方法也十分相似。只是当比较的两数差值比较大时,可能要进行多次减法才能达到一次除法的效果。
我们可以分别用以上两种方法计算一下 1997 和 615 的最大公约数,看看哪个计算次数更少。
辗转相除法:
更相减损法:
我们可以看到,当两数差值比较大时,辗转相除法计算的次数明显比更相减损法少。
4.stein算法
stein 算法就是那个我看了很久才看明白的算法……
比较
网络上很多人把 stein 算法与辗转相除法相比较。因为在 stein 算法之前,人们更常用的是辗转相除法,但是辗转相除法虽然相较暴力穷举法和更相减损法更高效,但是辗转相除法也有它的弊端。
简单地说就是当要计算的两个数很大很大很大很大很大很大的时候,除法运算就变得十分复杂,消耗很多时间,这时候一种不需要除法取模的 stein 算法就应运而生了。
之所以把 stein 算法放在更相减损法之后,是因为 stein 算法和更相减损法有相似之处。
在《九章算术》中,更相减损法的思想是:
可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
简单地说就是能折半(除以2)的就折半,不能折半就相减,直到减数与差相等为止。
而 stein 算法则要利用移位和相减来实现求最大公约数。
其实 stein 算法在常规的计算中并不占优势,但是由于按位运算相对除法和取模运算更简便,所以当所求的数很大很大很大很大的时候,stein 算法就相对更简单啦~
当然,我们在对常规的数字求最大公约数的时候,还是推荐使用辗转相除法和更相减损法。
运算符
首先我们要先把stein 运算中涉及到的相关运算符进行简单介绍。
Ps:以下这些运算符在《【手把手带你入门】初识C语言》一文中的操作符一节进行了介绍,这里仅根据需要进行简单介绍,需了解详情请点击文章名字跳转。
&
这里 & 的作用就是利用 x & 1 来判断 x 的奇偶性。
如上图,因为 &(相与)是只要有0则为0,所以我们可以得到
偶数 & 1 = 0 ;
奇数 & 1 = 1 ;
移位操作符
(<<)左移和(>>)右移是C语言中的移位操作符,在这里,我们求的是两个数的最大公约数,我们计算的数都是正整数。
以实际的数 6 为例子:
6 的二进制数是……… 0110 (暂时只写出4位)
6<<1 即往左移1位变为1100
转换为十进制数是 12,而 12 = 6 * 2;
6 >>1 即往右移1位变为0011
转换为十进制数是 3,而 3 = 6 / 2;
那如果是 5 呢?
5 的二进制数是……… 0101 (暂时只写出4位)
5<<1 即往左移1位变为1010
转换为十进制数是 10,而 10 = 5 * 2;
5 >>1 即往右移1位变为0010
转换为十进制数是 2,而 2 = 5 / 2 …… 1;
所以这里我们可以简单地把 <<1 理解为乘 2、>>1 位理解为除 2;x << = a 即为使 x 乘 2a。
原理
弄明白移位之后,我们再来看 stein 算法的基本原理:
gcd (kx , ky) = k * gcd (x , y) ;
上面这个式子大家应该都能看的明白,所以这里就把证明省略啦
步骤
下面我们以20、30为例用 stein 算法求自大公约数:
20、30 均为偶数,20 ÷ 2 = 10,30 ÷ 2 = 15;
10 为偶数、15 为奇数,10 ÷ 2 = 5;
5、15 均为奇数,15 - 5 = 10;
10 为偶数、5 为奇数,10 ÷ 2 = 5;
剩下两数均为 5
则 5 * 2 = 10 是 20 和 30 的最大公约数
stein 算法的步骤:文章来源:https://www.toymoban.com/news/detail-448683.html
若两个数都是偶数,则都除 >>1,记录次数;若两数为一奇一偶,则偶数 >>1 ;若两数均为奇数,则相减。
将得到的数重复执行步骤 1 直到得到的两个数相同。
若步骤 1 中两数都曾经 >>1,记录的次数为 n,则步骤 2 中得到的数再乘2n(<<n)即为两数的最大公约数。文章来源地址https://www.toymoban.com/news/detail-448683.html
到了这里,关于最大公约数的四种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!