求最大公约数

来源:互联网 发布:mac系统论坛 编辑:程序博客网 时间:2024/06/06 07:36

本文主要归纳了求最大公约数的几种方法,包括遍历法、欧几里得算法、 Stein算法等。

  • 遍历法
    这是一种比较直接、简单的方法。思路是:从两个数中选取一个较小的数作为遍历的起点,然后逐步减去1,寻找可能同时被两个数整除的约数。具体实现如下:
int traverse_Gcd(int n,int m){    int i=n>m?m:n;    for(;i>=1;i--){        if(n%i==0 && m%i==0){            return i;        }    }}
  • 欧几里得算法
    欧几里得算法,又称为辗转相除法。其应用的原理是:
    Gcd(a,b)=Gcd(b,a%b);
    解析:
    因为 a%b=a-(a/b)*b (1)
    所以 假设a,b的一个公约数为c,那么有a%c==0,b%c==0;
    我们把(1)式等号右边的式子,由减号分割为两部分,第一部分是a ,显然可以整除c;第二部分是(a/b)*b,因为b可以整除c,所以b与另外一个数的乘积依旧可以整除c,所以(a/b) *b 可以整除b。由此可以说明,a和b的最大公约数与b和a%b的最大公约数相同,以上式子成立。
    以下给出欧几里得算法的递归实现:
int Euclidean_GCd(int n,int m){    if(m==0){        return n;    }    Euclidean_GCd(m,n%m);}

以下给出欧几里得算法的迭代实现:

int Euclidean2_GCd(int n,int m){   if(m==0){    return n;   }   while(m!=0){    int t=m;    m=n%m;    n=t;   }   return n;}
  • 扩展的欧几里得算法
    已知整数n、m,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式:
    nx + my = Gcd(n, m); (1)
    由(1)式可得 , n’ x + m’ y = Gcd (n’,m’); (2)
    又 n’ = m;
    m’ = n % m = n - (n/m)* m;
    把n’ 和 m’ 代入 (2)式得
    m x + [ n - (n/m)*m ] y= Gcd (n’,m’);
    整理得
    ny + m (x- (n/m)y)=Gcd (n’,m’);
    故 x’ = y;
    y’ = x-(n/m)y;

代码如下:

int Extended_Euclidean_GCd(int n,int m,int* x,int* y){    if(m==0){        *x=1;        *y=0;        return n;    }else{    int r= Extended_Euclidean_GCd(m,n%m,x,y);    int t= *x;    *x = *y;    *y = t - (n/m)* *y;    return r;    }}

欧几里得算法采用的是辗转相除的方法,在一般情况下效率比较高。但是当在处理大整数时,由于除法运算的存在,该算法的效率大受影响。

  • Stein算法
    采用移位和减的方式来处理数据,没有除法运算,所以在求最大公约数时是比较高效。
    Stein算法原理如下:
    1.若a和b都是偶数,则记录下公约数2,然后都除2(即右移1位);
    2.若其中一个数是偶数,则偶数除2,因为此时2不可能是这两个数的公约数了
    3.若两个都是奇数,则a = |a-b|,b = min(a,b),因为若d是a和b的公约数,那么d也是a-b和min(a,b)的公约数。
    基于以上的原理,递归算法实现如下:
int Stein_Gcd(int a,int b){    int t;    if(a < b){        t = a;        a = b;        b = t;    }    if(b == 0)        return a;    if(a%2==0 && b%2==0){        return 2*Stein_Gcd(a/2,b/2);    }else if(a%2==0 && b%2!=0){        return Stein_Gcd(a/2,b);    }else if(a%2!=0 && b%2==0){        return Stein_Gcd(a,b/2);    }else {        return Stein_Gcd(a-b,b);    }}

参考链接:
https://www.cnblogs.com/drizzlecrj/archive/2007/09/14/892340.html
http://blog.csdn.net/workformywork/article/details/16368345

原创粉丝点击