终于想起来密码了嘤嘤嘤
好久没写过博客了,总感觉好生疏啊~~我的语言能力又退化惹~
废话不多说开始正题~
求两个数的最大公约数
首先我们来分析一下这个问题,什么是最大公约数?
*肯定能被这两个数整除
* 有可能小于或等于两个数之间较小的那个数。
这是最大公约数的特征。
那么根据它的特征,我们很容易就会想到,将所有的数都除一遍,然后再选择能除尽的数中最大的,作为最大公约数,这就是全部遍历的方法。
1. 全部遍历法
顾名思义,就是把从1开始到两个数之间最小的那个数中间的所有数都除一遍,最小的公约数肯定是1(两个素数之间),最大的公约数(最好情况下)是两个数之间最小的那个数。
因此,实现就可以用个一循环就搞定
\\假设求X和Y的最大公约数,且X>Y
int res=Y;
while(Y>0)
{
if(X%res==0&&Y%res==0)
printf("最大公约数为%d",res);
res--;
}
2. 辗转相减法
遍历法虽然求出了最大公约数,但是它将所有数都遍历了一遍,效率不高,因而我们可以换一种思路。
假设两个数之间的最大公约数是T,那么X就可以表示成n×T,Y则可以表示成m×T,那么(X-Y)就等于n×T-M×T=(n-m)×T=D,
显然X与Y的差D也和X,Y拥有相同的最大公约数,因此将求X和Y的最大公约数转换成取求D和Y的最大公约数,逐步缩小两个数之间的范围,当n-m=0时,最大公约数也就求出来了。具体实现如下:
\\
while(x!=y)
{
if(x>y)
{
x=x-y;
}else
{
y=y-x;
}
}
return x//因为最终x和y相等,所以返回谁都是一样的。
3. 辗转相除法
辗转相除法和辗转相减法在原理上有相似之处,X和Y之间存在最大公约数T,且X>Y,那么当 nX+mY=Z时(n,m可以是任何整数),Z也可以整除T。则当: X/Y=a…b
那么可将上式变为,X=aY+b ,b=X-aY
对应于式nX+mY=Z,b=1*X+(-a)Y,即b也可以整除T。
总之,上面这一堆说人话就是,在两个数之间,较大值除以较小值的余数,也和X与Y拥有相同的最大公约数T,因而,通过不断的求取二者之间的余数,直到一方的被除尽,也就是余数为0时,得出最大公约数T。所以代码实现如下所示:
\\ x!=y
while(x*y!=0)
{
if(x>y)
{
x%=y;
}else
{
y%=x;
}
return x+y;//因为最终会有一方为0,所以返回二者之和即可
}
总结
上述三种求最大公约数的方法,第一种最好理解,但是从效率层面来讲它不是最优的选择,第二种和第三种方法的思路较为相似,但是辗转相除法的轮数更少了,也就是二者之间计算的次数,因而辗转相除法较为优越一点。