求最大公约数

求两个数的最大公约数问题,即常说的GCD问题,是一个经常用到的问题。

这个问题的求解最常用的方法就是辗转相除的方法。这个方法其实就是下面的一个公式: 

gcd(a,b)=gcd(b,a%b)

记住了这个公式就很容易写出它的程序了。

第一:可以采用递归的方法:

unsigned gcd(unsigned a,unsigned b){
     if(!b)
         return a;
     if(a<b)
         return gcd(b,a);
     else
         return gcd(b,a%b);
}

第二:所有的递归都可以转为迭代实现:

unsigned gcd2(unsigned a,unsigned b)
{
    unsigned tmp;
     while(b!= 0)
    {
        tmp=a%b;
        a=b;
        b=tmp;
    }
     return a;
}

另一种不常见的方法是二进制gcd。 这种方法主要用到了gcd的如下几个性质:

// 1. 如果a,b都是偶数, 则gcd(a, b) = gcd(a/2, b/2)

 

// 2. 如果a是奇数, b是偶数,  则gcd(a, b) =  gcd(a, b/2)

 

// 3. 如果a,b都是奇数, 则gcd(a, b) = gcd((a-b)/2, b)

 

 

同样,如果采用递归的方式,代码如下:

unsigned binary_gcd(unsigned x,unsigned y){
     if(y== 0)
         return x;
     if(x<y)
         return gcd(y,x);
     else{
         if(((x|y)& 0x1)== 0)
             return  2*gcd(x>> 1,y>> 1);
         else  if((x& 0x1)== 0)
             return gcd(x>> 1,y);
         else  if((y& 0x1)== 0)
             return gcd(x,y>> 1);
         else
             return gcd(y,x-y);
    }
}

如果采用迭代方式,代码如下:

unsigned binary_gcd2(unsigned x,unsigned y)
{
    unsigned common_power_of_two= 0;
    unsigned tmp;
     if(x== 0)
         return y;
     if(y== 0)
         return x;
     while(((x|y)& 0x1)== 0)
    {
        x>>= 1;
        y>>= 1;
        ++common_power_of_two;
    }
     while((x& 0x1)== 0)
        x>>= 1;
     while(y)
    {
         while((y& 0x1)== 0)
            y>>= 1;
        tmp=y;
        y=(x>y)?x-y:y-x;
        x=tmp;
    }
     return x<<=common_power_of_two;

}

测试程序如下:

ExpandedBlockStart.gif View Code
#include <iostream>
#include <cstdlib>
#include <ctime>
using  namespace std;
unsigned gcd(unsigned a,unsigned b){
     if(!b)
         return a;
     if(a<b)
         return gcd(b,a);
     else
         return gcd(b,a%b);
}
unsigned binary_gcd(unsigned x,unsigned y){
     if(y== 0)
         return x;
     if(x<y)
         return gcd(y,x);
     else{
         if(((x|y)& 0x1)== 0)
             return  2*gcd(x>> 1,y>> 1);
         else  if((x& 0x1)== 0)
             return gcd(x>> 1,y);
         else  if((y& 0x1)== 0)
             return gcd(x,y>> 1);
         else
             return gcd(y,x-y);
    }
}

unsigned gcd2(unsigned a,unsigned b)
{
    unsigned tmp;
     while(b!= 0)
    {
        tmp=a%b;
        a=b;
        b=tmp;
    }
     return a;
}
unsigned binary_gcd2(unsigned x,unsigned y)
{
    unsigned common_power_of_two= 0;
    unsigned tmp;
     if(x== 0)
         return y;
     if(y== 0)
         return x;
     while(((x|y)& 0x1)== 0)
    {
        x>>= 1;
        y>>= 1;
        ++common_power_of_two;
    }
     while((x& 0x1)== 0)
        x>>= 1;
     while(y)
    {
         while((y& 0x1)== 0)
            y>>= 1;
        tmp=y;
        y=(x>y)?x-y:y-x;
        x=tmp;
    }
     return x<<=common_power_of_two;

}
int main()
{
    unsigned a,b;
   unsigned val,val2,val3,val4; 
    srand(time( 0));
     int i= 0;
     while(i< 1000)
    {
        a=rand()% 1000;
        b=rand()% 1000;
        val=gcd(a,b);
         if(val== 1)
             continue;
        val2=binary_gcd(a,b);
        val3=gcd2(a,b);
        val4=binary_gcd2(a,b);
        cout<<i<< ' \t ';
        cout<< " ( "<<a<< " , "<<b<< " )\t ";
        cout<<val<< ' \t '<<val2<< ' \t '<<val3<< ' \t '<<val4<< ' \t ';
         if(val==val2&&val2==val3&&val3==val4)
            cout<< " OK ";
         else
            cout<< " Bad ";
        cout<<endl;
        i++;
    }
     return  0;
}

测试结果如下图:

 

参考:http://www.cppblog.com/CodePanada/archive/2011/05/19/146743.html


 

 

转载于:https://www.cnblogs.com/xkfz007/archive/2012/07/02/2572434.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值