• 最大公约数的四种方法


    前言

    求两数的最大公约数,一共有四种方法:暴力穷举法、更相减损法、辗转相除法、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 算法的步骤:

    若两个数都是偶数,则都除 >>1,记录次数;若两数为一奇一偶,则偶数 >>1 ;若两数均为奇数,则相减。
    将得到的数重复执行步骤 1 直到得到的两个数相同。
    若步骤 1 中两数都曾经 >>1,记录的次数为 n,则步骤 2 中得到的数再乘2n(<

  • 相关阅读:
    矿物鉴定VR实践教学平台:打造全新的沉浸式学习体验
    Flutter插件开发指南01: 通道Channel的编写与实现
    【笔试题】【day17】
    Python---for循环中的两大关键字break和continue
    基于51单片机的环境温湿度光强监测系统proteus仿真原理图PCB
    《设计模式的运用》使用策略模式+工厂模式优化代码中的if else
    FTP客户端c代码功能实现
    【Phoenix】phoenix实现每个Primarykey主键保留N版本数据,CDC数据记录为Changelog格式
    柱状图 kate
    Vue3 从入门到放弃 (第四篇.Props使用)
  • 原文地址:https://blog.csdn.net/Hell_potato777/article/details/127132815