C语言求两个数的最大公约数和最小公倍数

前言

C语言中求最大公约数和最小公倍数是比较基础程序设计,以下为我的一些解决思路,如有错误,请给予指出斧正。


实现思路

最大公约数

方法一:循环

最大公约数为两个或多个整数共有约数中最大的一个。所以最大公约数一定小于或等于任意被除数,我们可以通过找到被除数中最小的数然后通过循环遍历的方式来试出最大公约数。

#define MIN(X,Y) ((X)<(Y)?(X):(Y))//用宏来求两个数中的最小值
 

int Find_GCD_V1(int x1, int x2)//x1,x2为需要求最大公约数的参数
{
    int ret = 0;
    int min = MIN(x1, x2);
    for (int i = min; i >= 1; i--)
    {
        if ((0 == x1 % i) && (0 == x2 % i))//将0放在左边能预防将‘==’写成‘=’而出现问题
        {
            ret = i;
            break;
        }
    }
    return ret;

方法二:辗转相除法

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

我们先来辗转相除法的原理及证明:

其计算原理依赖于下面的定理:

定理:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数。最大公约数(Greatest Common Divisor)缩写为GCD。

gcd(a,b) = gcd(b,a mod b) (不妨设a>b 且r=a mod b ,r不为0)

证明:

a可以表示成a = kb + r(a,b,k,r皆为正整数,且r不为0)

假设d是a,b的一个公约数,记作d|a,d|b,即a和b都可以被d整除。

而r = a - kb,两边同时除以d,r/d=a/d-kb/d,由等式右边可知m=r/d为整数,因此d|r

因此d也是b,a mod b的公约数。

因(a,b)和(b,a mod b)的公约数相等,则其最大公约数也相等,得证。

接下来我们看看实行方法

int Find_GCD_V2(int x1, int x2)
{
    int tmp = 0;
    while (tmp = x1 % x2)
    {
        x1 = x2;
        x2 = tmp;
    }
    return x2;

直到tmp为0为止,x1会不断的对x2进行取模,到最后循环停止时,x2的值就是x1、x2的最大公约数。

我们看到证明中设了x1>x2,但x1,x2谁大谁小会对结果有影响吗?下面我们以18、6和6、18两组数来举例。

C语言求两个数的最大公约数和最小公倍数_第1张图片

由图可知,不论谁大谁小, 最后当tmp==0的时候x2都是不会变的,只是当x1

 

最小公倍数

方法一:循环

两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。

类似于最大公约数,最小公倍数一定会大于或等于任意一个除数,所以我们可以通过循环的方式来试出两个数的最小公倍数。

#define MAX(X,Y) ((X)>(Y)?(X):(Y))//用宏来求两个数中的最大值

int Find_LCM_V1(int x1, int x2)//最小公倍数 遍历方法
{
    int ret = 0;
    int max= MAX(x1, x2);
    int tmp = max;
    while (1)
    {
        if ((0 == tmp % x1) && (0 == tmp % x2))
        {
            ret = tmp;
            break;
        }
        tmp++;
    }
    return ret;
}

方法一改进:

我们已知最小公倍数为两个数的整数倍。即可以写成LMC(最小公倍数)=x1*m且GCD=x2*n,m,n为整数。

那为什么我们还要逐个遍历呢?我们是不是可以只用x1、x2中其中一个数的各个倍数来测试就行了呢?答案是是的。

int Find_LCM_V2(int x1, int x2)
{
    int ret = 0;
    int i = 1;//倍数
    while (1)
    {
        int tmp = x1 * i;
        if ((0 == tmp % x1) && (0 == tmp % x2))
        {
            ret = tmp;
            break;
        }
        i++;
    }
    return ret;
}

我们只要从1倍也就是从某个数的本身出发,就不用担心x1,x2的大小关系了,又因为吗m,n都为整数,也不用担心用某个数的倍数来尝试会跳过两个数的最小公倍数了。

方法二:借助最大公因数求最小公倍数

两个数的乘积等于这两个数的最大公约数与最小公倍数的乘积。假设有两个数是a、b,它们的最大公约数是p,最小公倍数是q。那么有这样的关系:ab=pq。

所以我们可以写出以下程序

int Find_LCM_V3(int x1, int x2, int GCD)
{
    return x1 * x2 / GCD;
}

//你也可以将求最大公约数的过程集成到该函数内部


代码测试

C语言求两个数的最大公约数和最小公倍数_第2张图片C语言求两个数的最大公约数和最小公倍数_第3张图片

该测试也证明了 Find_GCD_V2函数和iFind_LCM_V2函数与x1和x2的大小关系无关。


结语

以上就是关于求两个数的最大公约数和最小公倍数的思路与看法,如有错误还请多多包涵并指正。谢谢浏览!

你可能感兴趣的:(小技巧,c语言)