最大公约数GCD的三种求法

作者: JxYoung | 来源:发表于2016-10-16 18:39 被阅读507次

最大公约数(GCD, Greatest Common Divisor,为简便下文都使用GCD表示最大公约数):指某几个整数共有约数中最大的一个。

由于多个数的GCD可以拆分成两个数的GCD,所以一般来说常见的是求两个数的GCD。废话不多说,来看看目前我已知的求GCD的方法。

  • 穷举法
  • 辗转相除法
  • 辗转相减法

下面来一个一个看。约定待求GCD的数为a, b。

1. 穷举法

这是最容易想到,而且是最直接的方法。简言之,就是从1开始,到a,b中比较小的那个结束,看能不能同时被a, b整除(如果能即为公约数),这样一个循环下来一定可以找出GCD。

代码如下:

    // 穷举法
    public static int gcd_enumeration(int a, int b){
        // 先找出a,b中小的那个
        int smaller = a;
        if (b < a) {
            smaller = b;
        }

        int gcd = 1;
        for (int i = 2; i <= smaller; i++) {
            // 如果能同时被a和b除尽,则更新GCD
            if ((a % i == 0) && (b % i == 0)) {
                gcd = i;
            }
        }
        return gcd;
    }

2. 辗转相除法

辗转相除法又称为欧几里得算法,大概公元前300年欧几里得老大爷就想出来这么个算法了,厉害了!

该方法依托于一个定理:

gcd(a, b) = gcd(b, a mod b)

其中,a mod b是a除以b所得的余数。

啥意思呢,就是说a,b的最大公约数就是b,a mod b的最大公约数。

证明如下:

(1)充分性:
设g是a,b的公约数,则a,b可由g来表示:
a = xg, b = yg (x,y为整数)
又,a可由b表示(任意一个数都可以由另一个数来表示):
a = kb + r (k为整数,r为a除以b所得余数)
=> r = a - kb = xg - kyg = (x - ky)g
即,g也是r的约数。
这样,g就是(b, r)即(b, a mod b)的公约数。

(2)必要性:
设g是(b, a mod b)的公约数,类似于(1),同样可以推出g也是(a, b)的公约数。

综合(1)(2)可得(a, b)和(b, a mod b)的公约数是一样的,当然最大公约数也是一样的。

好了,有了理论基础,下面总结成算法步骤:

  1. a % b得余数r
  2. 若r == 0,则b即为GCD
  3. 若r != 0,则a = b, b = r,返回步骤1

代码如下

    // 辗转相除法(递归写法)
    public static int gcd_division_recursive(int a, int b){
        if (b == 0) {
            return a;
        }
        return gcd_division_recursive(b, a % b);
    }

    // 辗转相除法(迭代写法)
    public static int gcd_division_iteration(int a, int b){
        while(b != 0){// 为什么用b判断呢?因为b就是用来存a%b的,即上面算法步骤里的r的
            int t = b;
            b = a % b;
            a = t;
        }
        return a;
    }

3. 辗转相减法

这个方法出处目前我也不知道,而且证明过程我也不知道,先写在这里,过后待我研究研究。

算法步骤:

  1. 若a > b,则a = a - b
  2. 若b > a,则b = b - a
  3. 若a == b,则a(或b)即为最大公约数
  4. 若a != b,则回到1

既然没有证明,那就举个栗子瞧瞧看吧。

求32,12的最大公约数:
32 - 12 = 20 (20 > 12)
20 - 12 = 8 (8 < 12)
12 - 8 = 4 (4 < 8)
8 - 4 = 4 (4 == 4)
所以最大公约数是4.

代码如下:

    // 辗转相减法(递归写法)
    public static int gcd_substract_recursive(int a, int b){
        if(a == b)
            return a;
        return a > b ? gcd_substract_recursive(a - b, b) : gcd_substract_recursive(a, b - a);
    }

    // 辗转相减法(迭代写法)
    public static int gcd_substract_iteration(int a, int b){
        // 如果a,b不相等,则用大的数减去小的数,直到相等为止
        while(a != b){
            if(a > b)
                a = a - b;
            else
                b = b - a;
        }
        return a;
    }

以上,我们知道了怎么求两个数的最大公约数,那最小公倍数呢?

其实,只要知道了a,b的最大公约数,那最小公倍数不就是a * b / gcd(a, b)吗?

完整代码

相关文章

  • 最大公约数&最小公倍数

    整数a整数b 最小公倍数 最小公倍数=a*b/最大公约数 最大公约数 最大公约数三种求法辗转相除法c=a%b;wh...

  • 最大公约数GCD的三种求法

    最大公约数(GCD, Greatest Common Divisor,为简便下文都使用GCD表示最大公约数):指某...

  • 自用算法模板(JAVA版)

    一、数论 1)GCD GCD(求最大公约数) QGCD(快速GCD) extGCD(拓展GCD,解决ax + by...

  • 笔试记录

    网易: 最大公约数,最小公倍数,素数的求法忘了 最大公约数: 辗转相除法: c++: ``` int main()...

  • 学习笔记《Base of Number theory》

    lcm, gcd gcd,greatest common divisor(最大公约数) lcm,least com...

  • 2019-02-12

    2019-02-1212.3 最大公约数和最小公倍数GCD函数返回两个或多个整数的最大公约数语法GCD(numbe...

  • 最大公约数和最小公倍数

    最大公约数 一般用gcd(a,b)来表示a和b的最大公约数,而求解最大公约数常用欧几里得算法(即辗转相除法) 如果...

  • 辗转相除法——字符串处理

    辗转相除法 GCD:辗转相除法,求两个正整数的最大公约数。 gcd(m,n) = gcd(n,m mod n) [...

  • 欧几里得算法心得(辗转相除法)

    辗转相除法是用来计算两个整数的最大公约数。假设两个整数为a和b,他们的公约数可以表示为gcd(a,b)。如果gcd...

  • 2019-10-26

    1071. Greatest Common Divisor of Strings GCD思想 我们学过求最大公约数...

网友评论

  • 暮雨沉沦:gcd第一时间想到的是我党。。。 :joy:
    JxYoung:@幻城下路miss :joy: 你很会联想
  • 王涪玖:有没有C语言的探讨,java不喜的。
    JxYoung:@王涪玖 这篇文章里的Java描述和C很相似的,并没有太多Java语言特性的东西,你可以自动忽略方法名那一行,核心内容在方法体里,而方法体和C的描述几乎是一样的 :relaxed:
  • 2c435657e370:辗转相除和辗转相减是一个方法,很容易看出减到比自己小和取模等价。辗转相减应该是出自九章算术,更相减损术。
    JxYoung:@homelesser 谢谢指正,已更新 :joy:
    2c435657e370:@JxYoung 另外,最后一句你提到的应该是最小公倍数:sweat:
    JxYoung: @homelesser 厉害了,word哥😂,学习了!

本文标题:最大公约数GCD的三种求法

本文链接:https://www.haomeiwen.com/subject/fpxayttx.html