一.辗转相除法
欧几里德的辗转相除法的执行过程如下:
⑴ 对于已知的两个自然数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;
}
运行结果如下:
四.穷举法
/*************************
作者: 马露露
编译器: 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;
}