最大公约数的常用算法

运行最大公约数的常用算法,并进行程序的调式与测试,要求程序设计风格良好,并添加异常处理模块(如输入非法等)。

算法构造

1.辗转相除法(又名欧几里德法)
①、大数放a中、小数放b中;
②、求a/b的余数;
③、若temp=0则b为最大公约数;
④、如果temp!=0则把b的值给a、temp的值给a;
⑤、返回第二步。
辗转相除法
2.穷举法从两个数中较小数开始由大到小列举,直到找到公约数立即中断列举,得到的公约数便是最大公约数 。在这里插入图片描述

3.更相减损法
①任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
②以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
则①中约掉的若干个2与②中等数的乘积就是所求的最大公约数。
其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。所以更相减损法也叫等值算法。在这里插入图片描述
4.Stein算法对两个正整数 x>y :
①均为偶数 gcd( x,y ) =2gcd( x/2,y/2 );
②均为奇数 gcd( x,y ) = gcd( (x+y)/2,(x-y)/2 );
③x奇y偶 gcd( x,y ) = gcd( x,y/2 );
④x偶y奇 gcd( x,y ) = gcd( x/2,y ) 或 gcd( x,y )=gcd( y,x/2 );
在这里插入图片描述

算法实现

1.辗转相除法

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int divisor (int a,int b)
{
  int  temp;
  if(a<b)
    { temp=a;a=b;b=temp;}
   while(b!=0)
    {
      temp=a%b;
      a=b;
      b=temp;
    }
  return (a);
}

int multiple (int a,int b)
{
  int divisor (int a,int b);
  int temp;
  temp=divisor(a,b);
  return  (a*b/temp);
}
//辗转相除法
int gcd (int a,int b)
{  if(a%b==0)
       return b;
else
       return gcd(b,a%b);
  }

//穷举法
int divisorr (int a,int b)
{
    int  temp;
    temp=(a>b)?b:a;
    while(temp>0)
    {
       if (a%temp==0&&b%temp==0)
          break;
       temp--;
    }
  return (temp);
}

//更相减损法
int gcdd(int m,int n)
{
 int i=0,temp,x;
 while(m%2==0 && n%2==0)
 {
  m/=2;
  n/=2;
  i+=1;
 }
 if(m<n)
 {
  temp=m;
  m=n;
  n=temp;
 }
 while(x)
 {
  x=m-n;
  m=(n>x)?n:x;
  n=(n<x)?n:x;
  if(n==(m-n))
   break;
 }
 if(i==0)
  return n;
 else
  return (int )pow(2,i)*n;
}

//Stein算法
int Stein( unsigned int x, unsigned int y )
{
        int factor = 0;
        int temp;
        if ( x < y )
        {
                temp = x;
                x = y;
                y = temp;
        }
        if ( 0 == y )
        {
                return 0;
        }
        while ( x != y )
        {
                if ( x & 0x1 )
                {
                        if ( y & 0x1 )
                        {
                                y = ( x - y ) >> 1;
                                x -= y;
                        }
                        else
                        {
                                y >>= 1;
                        }
                }
                else
                {
                        if ( y & 0x1 )
                        {
                                x >>= 1;
                                if ( x < y )
                                {
                                        temp = x;
                                        x = y;
                                        y = temp;
                                }
                        }
                        else
                        {
                                x >>= 1;
                                y >>= 1;
                                ++factor;
                        }
                }
        }
        return ( x << factor );
}

void main()
{
 int t1,t2,i,p,q,choose=1;
 int a[1000],b[1000];
 clock_t start, finish;
 double  totaltime;
 printf("数据个数:");
 scanf("%d",&q);
 srand((unsigned)time(NULL));
 for(i=0;i<=q;i++)
 {
  a[i]=rand()%250;
  b[i]=rand()%250;
 }
 printf("1.辗转相除法嵌套\n");
 printf("2.辗转相除法递归\n");
 printf("3.穷举法\n");
 printf("4.更相减损法\n");
 printf("5.Stein算法\n");
 while(choose)
 {
 printf("运用的算法:");
 scanf("%d",&p);
 switch(p)
   {
  case 1:
           start = clock();
           for(i=0;i<=q;i++)
     {
            t1=divisor(a[i],b[i]);
            t2=multiple(a[i],b[i]);
   printf("随机产生的两个数为:%d %d\n",a[i],b[i]);
            printf("最大公约数是 %d\n",t1);
            printf("最小公倍数是%d\n", t2);
     }
           finish = clock();
           totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
     printf( "辗转相除法嵌套需要时间为%f seconds\n", totaltime );break;

case 2:
    start = clock();
    for(i=0;i<=q;i++)
    {
    t1=gcd(a[i],b[i]);
    printf("最大公约数是 %d\n",t1);
       printf("最小公倍数是 %d\n",a[i]*b[i]/t1);
    }
       finish = clock();
       totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
    printf( "辗转相除法递归需要时间为%f seconds\n", totaltime );break;
   case 3:
    start = clock();
    for(i=0;i<=q;i++)
    {
    t1=divisorr(a[i],b[i]);
    printf("最大公约数是 %d\n",t1);
    }
    finish = clock();
       totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
    printf( "穷举法需要时间为%f seconds\n", totaltime );break;
   case 4:
    start = clock();
    for(i=0;i<=q;i++)
    {
    t1=gcdd(a[i],b[i]);
    printf("最大公约数是 %d\n",t1);
    }
    finish = clock();
       totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
    printf( "更相减损法需要时间为%f seconds\n", totaltime );break;
   case 5:
    start = clock();
    for(i=0;i<=q;i++)
    {
    t1=Stein(a[i],b[i]);
    printf("最大公约数是 %d\n",t1);
    }
    finish = clock();
       totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
    printf( "Stein算法需要时间为%f seconds\n", totaltime );break;
 }
 printf("\n继续查找选1,退出选0:");
 scanf("%d",&choose);
 if(choose==0)
  break;
 }
}

运行结果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值