最大公约数算法详解

一.辗转相除法


欧几里德的辗转相除法的执行过程如下:

⑴ 对于已知的两个自然数m和n,假设m>n。

⑵ 计算m除以n,将得到的余数记为r。

⑶ 如果r=0,则n为求得的最大公约数,否则执行下面一步。

⑷ 将n的值保存到m中(m=n),将r的值保存到n中(n=r),重复执行步骤(2)和(3),直到 r=0,便得到最大公约数。


实现代码如下:

/*************************
	作者: 马露露
	编译器: vc6.0
	创建时间: 2017.03.17
	修改时间: 2017.03.17
	描述: 从键盘输入两个整数,输出两个整数的最大公约数。
*************************/  

#include<iostream>
using namespace std;

/*辗转相除法求最大公约数*/
int gcd(int a,int b)
{
	int m,n,r;
	if(a>b)		//m为较大数,n为较小数
	{
		m=a;
		n=b;
	}
	else
	{
		m=b;
		n=a;
	}
	r=m%n;		//求余数
	while(r!=0)	//辗转相除
	{
		m=n;
		n=r;
		r=m%n;
	}
	return n;	//返回最大公约数
}

/*主函数*/
int main()
{
	int a,b,c;
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>a>>b;
		c=gcd(a,b);
		cout<<a<<"和"<<b<<"的最大公约数是:"<<c<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

运行结果如下:



二.Stein算法


假设计算a和b两个数的最大公约数,Stein算法的执行过程如下:

⑴首先判断a或b的值,如果a=0,b就是最大公约数;如果b=0,a就是最大公约数。如果a和b均不为0,则执行下一步。

⑵完成A1=a,B1=b,C1=c的赋值。

⑶判断An和Bn是否为偶数,若都是偶数,则使A(n+1)=An/2,B(n+1)=Bn/2,C(n+1)=Cn/2.如果判断An和Bn中包含一个奇数,则执行步骤(4)、(5)或(6)。

⑷若An是偶数,Bn是奇数,则完成A(n+1)=An/2,B(n+1)=Bn,C(n+1)=Cn的赋值。

⑸若Bn是偶数,An是奇数,则完成B(n+1)=Bn/2,A(n+1)=An,C(n+1)=Cn的赋值。

⑹若An和Bn都是奇数,则完成A(n+1)=|An-Bn|,B(n+1)=min(An,Bn),C(n+1)=Cn的赋值。

⑺n累加1,跳转到第(3)步进行下一轮运算。

在上面的执行过程中,反复用到除2和乘2的操作。其实乘2只需要将二进制整数左移一位,而除2只需要将二进制整数右移一位,这样的程序执行效率更高。


实现代码如下:

/*************************
	作者: 马露露
	编译器: vc6.0
	创建时间: 2017.03.17
	修改时间: 2017.03.17
	描述: 从键盘输入两个整数,输出两个整数的最大公约数。
*************************/  
#include<iostream>
using namespace std;
/*Stein算法*/
int gcd(int a,int b)
{
	int m,n,r;
	if(a>b)		//m为较大数,n为较小数
	{
		m=a;
		n=b;
	}
	else
	{
		m=b;
		n=a;
	}
	if(n==0)	//较小数为0
	{
		return m;	//m即为最大公约数
	}
	if(m%2==0 && n%2==0)	//m,n均为偶数
	{
		return 2*gcd(m/2,n/2); 
	}
	else if(m%2==0 && n%2!=0)
	{
		return gcd(m/2,n);
	}
	else if(m%2!=0 && n%2==0)
	{
		return gcd(m,n/2);
	}
	else
	{
		return gcd((m-n),n);
	}
}

/*主函数*/
int main()
{
	int a,b,c;
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>a>>b;
		c=gcd(a,b);
		cout<<a<<"和"<<b<<"的最大公约数是:"<<c<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}


运行结果如下:


三.相减法


相减法求最大公约数的思路如下:

⑴对于已知的两个自然数a和b,如果a>b,则a=a-b;如果b>a,则b=b-a。

⑵判断a和b是否相等,如果不相等,则继续从步骤(1)开始执行;如果相等,则结束循环,输出最大公约数。


实现代码如下:

/*************************
	作者: 马露露
	编译器: vc6.0
	创建时间: 2017.03.17
	修改时间: 2017.03.17
	描述: 从键盘输入两个整数,输出两个整数的最大公约数。
*************************/  

#include<iostream>
using namespace std;

/*相减法求最大公约数*/
int gcd(int a,int b)
{
	while(a!=b)
	{
		if(a>b)
			a=a-b;
		else
			b=b-a;
	}
	return a;
}

/*主函数*/
int main()
{
	int a,b,c;
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>a>>b;
		c=gcd(a,b);
		cout<<a<<"和"<<b<<"的最大公约数是:"<<c<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

运行结果如下:



四.穷举法


穷举法求最大公约数的思路如下:
⑴对于已知的两个自然数a和b,假设a>b,则穷举的范围是1到b。
⑵当分别用a和b除以r时都能整除,余数为0的那个r就是最大公约数。

实现代码如下:
/*************************
	作者: 马露露
	编译器: vc6.0
	创建时间: 2017.03.17
	修改时间: 2017.03.17
	描述: 从键盘输入两个整数,输出两个整数的最大公约数。
*************************/  
#include<iostream>
using namespace std;

/*穷举法*/
int gcd(int m,int n)
{
	int r=1;
	int p=0;
	if(m>n)
	{
		r=m;
		m=n;
		n=r;
	}
	while(r<=m)
	{
		if(((m%r)==0) && ((n%r)==0))
			p=r;
		r++;
	}
	return p;
}

/*主函数*/
int main()
{
	int a,b,c;
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>a>>b;
		c=gcd(a,b);
		cout<<a<<"和"<<b<<"的最大公约数是:"<<c<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

运行结果如下:


五.程序整合


/*************************
	作者: 马露露
	编译器: vc6.0
	创建时间: 2017.03.17
	修改时间: 2017.03.17
	描述: 从键盘输入两个整数,输出两个整数的最大公约数。
*************************/  

#include<iostream>
using namespace std;
int select=1;//select为是否退出系统的标记
/*辗转相除法*/
int gcd1(int m,int n)
{
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>m>>n;
		int r;
		r=m%n;		//求余数
		while(r!=0)	//辗转相除
		{
			m=n;
			n=r;
			r=m%n;
		}
		cout<<"最大公约数是:"<<n<<endl;
		cout<<"继续请输入1,返回上一级请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

/*Stein算法*/
int gcd2(int a,int b)
{
	int m,n;
	if(a>b)		//m为较大数,n为较小数
	{
		m=a;
		n=b;
	}
	else
	{
		m=b;
		n=a;
	}
	if(n==0)	//较小数为0
	{
		return m;	//m即为最大公约数
	}
	if(m%2==0 && n%2==0)	//m,n均为偶数
	{
		return 2*gcd2(m/2,n/2); 
	}
	else if(m%2==0 && n%2!=0)
	{
		return gcd2(m/2,n);
	}
	else if(m%2!=0 && n%2==0)
	{
		return gcd2(m,n/2);
	}
	else
	{
		return gcd2((m-n),n);
	}
}

/*相减法*/
int gcd3(int m,int n)
{
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>m>>n;
		while(m!=n)
		{
			if(m>n)
				m=m-n;
			else
				n=n-m;
		}
		cout<<"最大公约数是:"<<m<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

/*穷举法*/
int gcd4(int m,int n)
{
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>m>>n;
		int r=1;
		int p=0;
		if(m>n)
		{
			r=m;
			m=n;
			n=r;
		}
		while(r<=m)
		{
			if(((m%r)==0) && ((n%r)==0))
				p=r;
			r++;
		}
		cout<<"最大公约数是:"<<p<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

/*显示Stein算法所求结果*/
int output()
{
	int a,b,c;
	int choose=1;
	while(choose)
	{
		cout<<"输入两个正整数(空格隔开):"<<endl;
		cin>>a>>b;
		c=gcd2(a,b);
		cout<<"最大公约数是:"<<c<<endl;
		cout<<"继续请输入1,结束请输入0"<<endl;
		cin>>choose;
	}
	return 0;
}

/*主菜单*/
int menu()
{  
	int item,m,n;
	cout<<endl;	
	cout<<"************************"<<endl;
	cout<<"*     1.辗转相除法     *"<<endl;
	cout<<"*     2.Stein算法      *"<<endl;
	cout<<"*     3.相减法         *"<<endl;
	cout<<"*     4.穷举法         *"<<endl;
	cout<<"*     5.退出           *"<<endl;
	cout<<"************************"<<endl;
	cout<<endl;
	cout<<"请选择您需要的操作序号(1-4)按回车确认:"<<endl;	
	cin>>item;
	switch(item)
	{
		case 1:
			system("cls");
			gcd1(m,n);
			break; 
		case 2:
			system("cls");
			output();
			break;
		case 3:
			system("cls");
			gcd3(m,n);
			break;
		case 4:
			system("cls");
			gcd4(m,n);
			break;
		case 5:
			select=0;
			break;
		default:
			printf("请在1-5之间选择\n");
	}
	return 0;
}

/*主函数*/
int main()
{
	while(select)
	{
		menu();
	}
	system("pause");
	return 0;
}





发布了31 篇原创文章 · 获赞 48 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/mall_lucy/article/details/63684730