求取最大公因数


一.题目名称:用不同的算法求最大公约数。
二.题目背景:通过使用“辗转相除法”“穷举法”“更相减损法”“Stein算法”来计算最大公因数,并且比较四种方法各自使用的时间。
三.题目分析:不同的方法有不同的解题步骤与思路,此题要求用四种不同的算法来计算最大公因数并且进行时间比较,我的想法是利用一个主函数分别调用四个函数算法,定义一个时间函数来计算时间,初始化一个随机数序列方便测试,因为四种算法是用两个整型数进行比较,而若要进行时间比较,一组数据是远远不够的,所以我的想法是,定义一个函数,将产生的随机数保存在一个数组内存在函数中,再逐个的进行运用与调用来完成时间比较。
四.所用方法
1.辗转相除法
算法过程:1.设两数为a,b设其中a做被除数,b做除数,t为余数
2.较大值存于a,较小值存于b 
3.求a%b的余数赋值于t;
4.若t=0则b为最大公约数;
5.如果t!=0,则将b的值赋给a、b的值赋给t,返回第二步后再次进行计算。
算法代码:
void divisor1(int a,int b)
{
    int t;                        //定义一个整型变量
    if(a<b)                       //判断输入a,b的大小  
    {
        t=a;a=b;b=t;              //交换大小
    }
    while(b!=0)                   
    {
        t=a%b;                    //求余
        a=b;                      //互换
        b=t;
    }
    cout<<"the highest common divisor is "<<a<<endl;
}
算法流程图:

 
2.穷举法
算法过程:1.设两数为a,b,并且定义一个t;
          2.比较a,b大小,将较小值赋给t;
3.若t大于0,则进行判断,截止条件为当a,b同时将t整除时,t为最大公因数;
4.若不符合截止条件,则t进行递减继续进行第三步。
算法代码:
void divisor2(int a,int b)             
{

    int t;
    t=(a>b)?b:a;                      //将较小值赋给t
    while(t>0)
    {
        if(a%t==0 && b%t==0)          //截止条件为a,b同时可以将t整除
        {
            break;
        }
        t--;                          //t递减直到可以整除为止
    }
    cout<<"the highest common divisor is "<<t<<endl;
}
算法流程图:


3.更相减损法
算法过程:1.设两数为a,b,并且定义i为0,t,x;
          2.给定两个整数,判断他们是否都是整数,若为整数,则用2约简,并且记录约简次数i内,若不是则继续进行;
3.判断a,b的大小,较大值赋给a,较小值赋给b;
4.设x为较大值减去较小值之差,若x大于0,利用b与x比较大小,较大值赋给a,较小值赋给b,若b与x相等则输出判断,若i为0,则b为最大公因数,若i不为0,则最大公因数为(2^i)*b;
5,若b与x不相等,则继续进行第四步,直到输出。
算法代码:
void gcd(int a,int b)
{
    int i=0,t,x;
    while(a%2==0 && b%2==0)          // 判断a,b能被多少个2整除
    {
        a/=2;
        b/=2;
        i+=1;
    }
    if(a<b)                         //判定a,b的大小,较大值赋给a,较小值赋给b
    {
        t=a;
        a=b;
        b=t;
    }
    while(x)                         
    {
        x=a-b;
        a=(b>x)?b:x;                //将较大值赋给a
        b=(b<x)?b:x;                //将较小值赋给b
        if(b==(a-b))            
            break;
    }
    if(i==0)
        cout<<"the highest common divisor is "<<b<<endl;
    else
        cout<<"the highest common divisor is "<<(int)pow(2,i)*b<<endl;   //pow(2,i)函数意义为2^i
}
算法流程图:
 
4.Stein算法
算法过程:1.定义两个整型无符号数a,b,并且定义factor为0,t;
2.判断a,b的大小,较大值赋给a,较小值赋给b;
3.判断b是否为0,若为0则最大公因数为0,若b不是0,则继续进行;
4.若a不等于b,则进行判断,分别判断a偶b偶,a偶b奇,a奇b偶,a奇b奇四种形式,(当a,b都为偶时,factor进行递增),直到a等于b是,最大公因数为a向左移动factor个距离。
算法代码:
void Stein(unsigned int a,unsigned int b)
{
    int factor=0;
    int t;
    if(a<b)             //判断a,b的大小,将较大值赋给a,较小值赋给b
    {
        t=a;
        a=b;
        b=t;
    }
    if(b==0)
    {
        cout<<0<<endl;               //如果b为0,则输出
    }
    while (a!=b)
    {
        if(a & 0x1)   //判断a是否为奇数,相当于取a的二进制中最右边的数字
        {
            if(b & 0x1)       //判断b是否为奇数,相当于取b的二进制中最右边的数字
            {
                b=(a-b)>>1;          //  >>是右移运算符
                a-=b;
            }
            else
            {
                b>>=1;        // ">>="为右移后赋值运算符    相当于 b=b>>1
            }
        }
        else
        {
            if(b & 0x1)           
            {
                a>>=1;
                if(a<b)            //进行判断,将较大值赋给a,较小值赋给b
                {
                    t=a;
                    a=b;
                    b=t;
                }
            }
            else
            {
                a>>=1;
                b>>=1;
                ++factor;
            }
        }
    }
    cout<<"the highest common divisor is "<<(a<<factor)<<endl;
}
算法流程图:

五.程序源代码

#include <iostream.h>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <stdlib.h>
#define N 5                                           

int divisor1(int m,int n);
int divisor2(int m,int n);
int gcd(int m,int n);
int Stein(unsigned int m,unsigned int n);
void array1(int a[],int b[]);

void main()
{	
	int i,j;

    int arr[N],brr[N],arr_s[N],brr_s[N];          //前两个用于计算,后两个用于备份

	srand(time(0));                               //初始化一个随机数序列,为了随机,一般用time(0)

	for (i = 0; i<N; i++)
		arr_s[i] = rand()%1000;                   //从随机数序列中依次抓取一个正整数  0到1000区间内

	for (j = 0; j<N; j++)
		brr_s[j] = rand()%1000; 

	clock_t start,finish;                         //定义时间函数

	int Time[4];
	int input;                                    //输入数据

	do
	{
		cout<<"********************************"<<endl;
		cout<<"1--辗转相除法       2--穷举法"<<endl;
		cout<<"3--更相减损法       4--Stein算法"<<endl;
		cout<<"0--退出                         "<<endl;
		cout<<"********************************"<<endl;
		cout<<"please input a number:"<<endl;
		cin>>input;
		for (i = 0; i<N; i++)
			arr[i] = arr_s[i];                    //复制一份数组用于计算
	    for (j = 0; j<N; j++)
			brr[j] = brr_s[j];  
		switch(input)                             //选择所要查看的方法
		{
		case 1:
			cout<<"辗转相除法"<<endl;
			start=clock();
			array1(arr,brr);
			finish=clock();
			Time[input]=finish-start;
	        cout<<"The 辗转反侧法 run time of the computer is "<<Time[input]<<"ms"<<endl;
			break;
		case 2:
			cout<<"穷举法"<<endl;
			start=clock();
			array1(arr,brr);
			finish=clock();
            Time[input]=finish-start;
	        cout<<"The 穷举法 run time of the computer is "<<Time[input]<<"ms"<<endl;
			break;
		case 3:
			cout<<"更相减损法"<<endl;
			start=clock();
			array1(arr,brr);
			finish=clock();
            Time[input]=finish-start;
	        cout<<"The 更相减损法 run time of the computer is "<<Time[input]<<"ms"<<endl;
			break;
		case 4:
			cout<<"Stein算法"<<endl;
			start=clock();
			array1(arr,brr);
			finish=clock();
			Time[input]=finish-start;
	        cout<<"The Stein算法 run time of the computer is "<<Time[input]<<"ms"<<endl;
			break;
		case 0:
			break;
		default:
			break;
		}
		if(input!=0 && input!=1 && input!=2 && input!=3 && input!=4)
		{
			cout<<"wrong input"<<endl;
		}

	}while(input);
}

void array1(int a[],int b[])                           //重新定义一个函数,将数组保存在内
{
	int m,n,i,j,x,t;
    cout<<"please input a number"<<endl;
	cin>>x;
	if(i<N && j<N)
	{
		for(i=0;i<N;i++)
		{
	    	m=a[i];                                     //将a[i]的数值保存在m中
			cout<<"m["<<i<<"]="<<m<<endl;
    	    for(j=0;j<N;j++)
			{
	        	n=b[j];                                 //将b[j]的数值保存在n中
		    	cout<<"n["<<j<<"]="<<n<<endl;
				if(x==1)
				{
		    	    divisor1(m,n);
				}
				else if(x==2)
				{
					divisor2(m,n);
				}
				else if(x==3)
				{
					gcd(m,n);
				}
				else if(x==4)
				{
					Stein(m,n);
				}
			}
		}
	}
}


//辗转相除法
int divisor1(int a,int b)
{
	int t;                        //定义一个整型变量
	if(a<b)                       //判断输入a,b的大小  
	{
		t=a;a=b;b=t;              //交换大小
	}
	while(b!=0)                   
	{
		t=a%b;                    //求余
		a=b;                      //互换
		b=t;
	}
    cout<<"the highest common divisor is "<<a<<endl;
    return(0);
}

			
//穷举法
int divisor2(int a,int b)             
{

	int t;
	t=(a>b)?b:a;                      //将较小值赋给t
	while(t>0)
	{
		if(a%t==0 && b%t==0)          //截止条件为a,b同时可以将t整除
		{
			break;
		}
		t--;                          //t递减直到可以整除为止
	}
    cout<<"the highest common divisor is "<<t<<endl;
	return(0);
}

//更相减损法
int gcd(int a,int b)
{
	int i=0,t,x;
	while(a%2==0 && b%2==0)          // 判断a,b能被多少个2整除
	{
		a/=2;
		b/=2;
		i+=1;
	}
	if(a<b)                         //判定a,b的大小,较大值赋给a,较小值赋给b
	{
		t=a;
		a=b;
		b=t;
	}
	while(x)                         
	{
		x=a-b;
		a=(b>x)?b:x;                //将较大值赋给a
		b=(b<x)?b:x;                //将较小值赋给b
		if(b==(a-b))            
			break;
	}
	if(i==0)
        cout<<"the highest common divisor is "<<b<<endl;
	else
	    cout<<"the highest common divisor is "<<(int)pow(2,i)*b<<endl;   //pow(2,i)函数意义为2^i
	return 0;

}

//Stein算法
int Stein(unsigned int a,unsigned int b)
{
	int factor=0;
	int t;
	if(a<b)                          //判断a,b的大小,将较大值赋给a,较小值赋给b
	{
		t=a;
		a=b;
		b=t;
	}
	if(b==0)
	{
		cout<<0<<endl;               //如果b为0,则输出
	}
	while (a!=b)
	{
		if(a & 0x1)                  //判断a是否为奇数,相当于取a的二进制中最右边的数字
		{
			if(b & 0x1)              //判断b是否为奇数,相当于取b的二进制中最右边的数字
			{
				b=(a-b)>>1;          //  >>是右移运算符
				a-=b;
			}
			else
			{
				b>>=1;               // ">>="为右移后赋值运算符	相当于 b=b>>1
			}
		}
		else
		{
			if(b & 0x1)           
			{
				a>>=1;
				if(a<b)              //进行判断,将较大值赋给a,较小值赋给b
				{
					t=a;
					a=b;
					b=t;
				}
			}
			else
			{
				a>>=1;
				b>>=1;
				++factor;
			}
		}
	}
    cout<<"the highest common divisor is "<<(a<<factor)<<endl;
	return(0);
}

六.验证.测试及调试
1.验证
       我的想法是提前定义一个数组,将随机数存入数组中,在一个一个赋值给m和n,为了保证验证准确性,每一组数的数值都相同,四种方法所用到的数字都是相同的,不存在不同的算法有不同的随机数。
我提前定义一个N,通过循环得到每一组m和n,具体在代码中,所以每定义一个N都意味着有N^2组数据进行验证。

2.测试(验证每种方法是否可用)
1)辗转相除法
 
图一
2)穷举法
 
图二

3)更相减损法
 
图三
4)Stein算法
 
图四
测试结果:将四种算法分别进行了验证,都可以成功的输出结果,且结果均正确,接下来将四种算法合并到一个程序中进行验算以及调试。

3.调试
调试时我定义N为2,这样方便调试
 
图五
 
图六
 
图七
 
图八
 
图九
七.总结
    就四种算法的时间比较看来,当数据越多,更相减损法和Stein算法花费的
时间较少。
整段代码还存在着一些问题,像定义一个N时需要去重新改正,调用函数的时候可能过于麻烦,接下来还需要时间去研究学习一些方法去优化。
这个代码整体不算复杂,每一步都有相对应的程序代码,但是为了更好地掌握还是需要时间去研究。


 

发布了16 篇原创文章 · 获赞 3 · 访问量 1108

猜你喜欢

转载自blog.csdn.net/qq_41890177/article/details/88364987
今日推荐