给定两个数,求这两个数的最大公约数
一、辗转相除法
1.概念
辗转相除法也叫欧几里得算法,是一种非常古老的求解两个数的最大公约数的算法。
其基于的原理:两个正整数a和b(a > b),它们的最大公约数gcd等于a除以b的余数r和b之间的最大公约数。
比如,10和25的最大公约数5等于25除以10的余数5和10的最大公约数;再比如51和21的最大公约数3等于51除以21的余数9和21的最大公约数,而9和21的最大公约数为3。
根据上面的原理,辗转相除法的算法流程可以如下:
步骤1:计算a与b的余数r。
步骤2:如果r为0,则返回gcd = b。否则,转到步骤3。
步骤3:使用b的值更新a的值,使用余数r更新b的值,转到步骤1。
2.C语言实现
int main ( )
{
int m = 0 ;
int n = 0 ;
int r= 0 ;
scanf ( "%d%d" , & m, & n) ;
while ( r = m % n)
{
m = n;
n = r;
}
printf ( "%d" , n) ;
return 0 ;
}
3.缺点
辗转相除法实现时因为使用了求余运算的缘故导致其在面对大整数的时候性能不够理想。
我们应尽量避免使用求余运算。
二、更相减损术
1.概念
更相减损术出自《九章算术》,其原理很简单:两个正整数a和b(a > b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。
依次递归下去,直到两个数相等。这相等两个数的值就是所求最大公约数。
根据以上原理,更相减损术的算法流程可以如下:
步骤1:计算a与b的差值c
步骤2:如果c为0,则返回gcd = b。否则,转到步骤3。
步骤3:使用b的值更新a的值,使差值c更新b的值,转到步骤1。
2.C语言实现
int main ( )
{
int a = 0 ;
int b = 0 ;
int c = 0 ;
scanf ( "%d %d" , & a, & b) ;
if ( a < b)
{
int temp = a;
a = b;
b = temp;
}
while ( c = a - b)
{
if ( b < c)
{
int temp = b;
b = c;
c = temp;
}
a = b;
b = c;
}
printf ( "%d" , b) ;
return 0 ;
}
3.缺点
更相减损术虽然避免了求余运算,但当两个数a和b相差太过悬殊时,递归的次数会非常多,严重影响算法性能。