【精选】一文搞定最大公约数(四种方法,赋原理和比较,超详细解答)

您所在的位置:网站首页 如何用python求两个数的最大公约数 【精选】一文搞定最大公约数(四种方法,赋原理和比较,超详细解答)

【精选】一文搞定最大公约数(四种方法,赋原理和比较,超详细解答)

2023-11-19 03:56| 来源: 网络整理| 查看: 265

最大公约数 前言1.暴力穷举法代码 2.辗转相除法步骤原理代码 3.更相减损法步骤原理代码比较 4.stein算法比较运算符&移位操作符 原理步骤代码

在这里插入图片描述

前言

求两数的最大公约数,一共有四种方法:暴力穷举法、更相减损法、辗转相除法、stein 算法,小女不才,花了几天的时间终于把这几种方法全部弄明白(尤其是stein 算法,看了好久才终于看懂……),现在就把它们全部分享出来。

首先,假设被求的两个数为 x、y,且 x > y。最大公约数 d = gcd (x , y)

1.暴力穷举法

正如名字所说,暴击穷举法就是简单粗暴地把 1~ y(前面已经假设 x > y)都列出来分别判断是否为 x、y 的公约数,然后再找到其中最大的一个。

暴力穷举法最大的特点就是简单直接、很容易理解,但是计算比较繁琐。

不过是计算机算又不是我算:无所谓啦(偷笑) 在这里插入图片描述

代码 #include int main() { int x = 0; int y = 0; int i = 0; scanf("%d %d", &x, &y);//输入两数 if (x if (x % i == 0 && y % i == 0)//最先出现的能被两个数整除的数就是公约数 { printf("最大公约数为%d\n", i); break; } } return 0; }

运行如下: 在这里插入图片描述

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 )

代码 #include int main() { int x = 0; int y = 0; scanf("%d %d", &x, &y); while (1) { if (x printf("最大公约数的 %d\n", y); break; } else//若余数不为 0,则令 x = y,y = 余数,重复循环 { int tmp = x % y; x = y; y = tmp; } } return 0; } 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);

代码 #include int main() { int x = 0; int y = 0; scanf("%d %d", &x, &y); while (1) { if (x printf("最大公约数的 %d\n", y); break; } else//若差不为 0,则令 x = y,y = 差,重复循环 { int tmp = x - y; x = y; y = tmp; } } return 0; }

运行结果: 在这里插入图片描述

比较

这里我们可以将更相减损法和辗转相除法进行比较:

将上面两个实例中的式子稍稍变形: 辗转相除法 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位) 61 即往右移1位变为0011 转换为十进制数是 3,而 3 = 6 / 2;

那如果是 5 呢?

5 的二进制数是……… 0101 (暂时只写出4位) 51 即往右移1位变为0010 转换为十进制数是 2,而 2 = 5 / 2 …… 1;

所以这里我们可以简单地把 1 位理解为除 2;x >1,记录次数;若两数为一奇一偶,则偶数 >>1 ;若两数均为奇数,则相减。将得到的数重复执行步骤 1 直到得到的两个数相同。若步骤 1 中两数都曾经 >>1,记录的次数为 n,则步骤 2 中得到的数再乘2n( if (x if (y & 1 == 0)//两数均为偶数时 { x >>= 1; y >>= 1; count++;//计算两数均除2的次数 } else//x为偶数、y为奇数 { x >>= 1; } } else { if (y & 1 == 0)//x为奇数、y为偶数 { y >>= 1; } else//两数均为奇数 { int tmp = x - y; x = y; y = tmp;//y = 0 时while后的表达式为假,循环停止,得到x } } } return (x



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3