您的位置:首页 > 编程语言 > C语言/C++

【算法】用c/c++求两正整数的最大公约数

2017-03-22 19:17 176 查看
最近想学的东西很多,方向也很杂,希望能通过写博客来记录自己已学的知识和有疑惑的地方,起到总结的作用,因为自己所知甚少,所以更要一步一步地慢慢积累。

【要求】用c/c++求两数的最大公约数。

【背景】:最大公约数指两个或多个整数共有约数中最大的一个。求最大公约数的常见的有质因数分解法、短除法、辗转相除法、更相减损发。

【分析】在此我用三种算法来解决这个问题:

             
1.辗转相除法

                【步骤】

          ① a%b得余数c

          ② 若c=0,则b即为两数的最大公约数

          ③ 若c≠0,则a=b,b=c,再回去执行①
             
2.Stein算法

                【步骤】

      若求两数的最大公约数的函数为gcd(a,b)

      ① 若a=0,则b为两数的最大公约数

      若b=0,则a为两数的最大公约数

     
② 若a和b都是偶数,则两数的最大公约数为2*gcd(a/2,b/2)(递归)

      ③
若a是偶数,b都是奇数,则两数的最大公约数为gcd(a/2,b)(递归)

      ④
若a是奇数,b都是偶数,则两数的最大公约数为gcd(a,b/2)(递归)

      ④ 若a、b都是奇数,则两数的最大公约数为gcd(|a-b|,min(a,b))(递归)

             
3.更相减损术

                【步骤】

          ① 若a>b,则a=a-b

          ② 若a<b,则b=b-a

          ③ 若a=b,则a(或b)即为两数的最大公约数

          ④ 若a≠b,则再回去执行①
【问题】在输入数据的检测上,还是存在不少BUG,
 
              1.输入整数时,如果输入“ww”可以正常提示错误,也能继续输入。但输入"www"时,虽然也会提示错误,但无法继续输入数据。

 
              2.在选择是否继续执行程序时,选“1”继续之后,会多出现一行提示输入为”0“的提示,但程序可以运行。
【反思】

 1.写程序也需要一定的数学思想,求两正整数的最大公约数这样的一个问题根据不同的数学的思想就能编出不同的算法,对于算法,我还有
许多没想明白的地方,需要更多地思考。
 
              2.想让某个整型变量a除以2,a>>2比a/2的效率更高,慢慢积累一些编程的小技巧,可以让写出来的程序更加高效。

                3. 一个可以使用的程序,对于输入检测的要求也很高,需要考虑到用户各个可能的输入,不然程序就有可能崩溃。而对于输入进行检测也有许多的知识需要学习。

【源程序】

#include<iostream>
using namespace std;

/************算法1:用辗转相除法求最大公约数************/
int gcdFuctionOne(int numberOne,int numberTwo)
{
int remain;
/*余数*/

while(1)
{
remain=numberOne%numberTwo;
numberOne=numberTwo;
numberTwo=remain;
if(remain==0) /*若余数为0,就跳出循环,否则继续循环*/
{
break;
}
}/*while结束*/
return numberOne;
}

/*辗转相除法求最大公约数的递归实现*/
int gcdFuctionOneOther(int numberOne,int numberTwo)
{
return numberOne%numberTwo?gcdFuctionOne(numberTwo,numberOne%numberTwo):numberTwo;
}

/*求两者的较小值*/
int min(int numberOne , int numberTwo)
{
return numberOne<numberTwo?numberOne:numberTwo;
}
/*求两者的较大值*/
int max(int numberOne , int numberTwo)
{
return numberOne>numberTwo?numberOne:numberTwo;
}

/************算法2:用Stein算法求最大公约数************/
int gcdFuctionTwo(int numberOne,int numberTwo)
{
if(numberOne == 0) return numberTwo;/*如果numberOne=0,numberTwo是最大公约数*/
if(numberTwo == 0) return numberOne;/*如果numberTwo=0,numberOne是最大公约数*/

if(numberOne % 2 == 0 && numberTwo % 2 == 0) /*如果numberOne、numberTwo都是偶数,把它们分别除以2,然后递归*/
{
return 2 * gcdFuctionTwo(numberOne >> 1, numberTwo >> 1);
}
else if(numberOne % 2 == 0)/*如果numberOne是偶数,把它除以2,然后递归*/
{
return gcdFuctionTwo(numberOne >> 1, numberTwo);
}
else if(numberTwo % 2 == 0) /*如果numberTwo是偶数,把它除以2,然后递归*/
{
return gcdFuctionTwo(numberOne , numberTwo >> 1);
}
else/*如果都不是偶数,将两者之差和两者中较小值代入函数进行递归*/
{
return gcdFuctionTwo(abs(numberOne - numberTwo), min(numberOne , numberTwo));
}
}

/************算法3:用更相减损术求最大公约数************/
int gcdFuctionThree(int numberOne,int numberTwo)
{
int remain1,remain2;/*remain1,remain2是两数的差*/
int er = 1;/*用于记录约掉了几个2*/

while(1)
{
for(;numberOne % 2 == 0 && numberTwo % 2 == 0;) /*如果numberOne、numberTwo都是偶数,把它们分别除以2*/
{
numberOne=numberOne/2;
numberTwo=numberTwo/2;
er=er*2;
}
remain1 = max(numberOne,numberTwo)-min(numberOne,numberTwo);/*以numberOne和numberTwo中较大的数减较小的数*/
remain2 = max(remain1,min(numberOne,numberTwo))-min(remain1,min(numberOne,numberTwo));/*把所得的差与较小的数比较,并以大数减小数*/
numberTwo=min(numberOne,numberTwo);
numberOne=remain1;
if(remain1==remain2) /*若上步所得的减数和差相等,就跳出循环,否则继续循环*/
{
break;
}
}/*while循环结束*/
return er*remain1;/*for循环中约掉的若干个2与remain1或remain2的乘积就是所求的最大公约数*/
}

/*主函数*/
int main()
{
double choice;/*choice为用户的选择*/
char num1[20];
char num2[20];
int n1,n2;
int cg;

cout<<"[**************本程序用于计算两个整数的最大公约数**************]"<<endl;
/*循环开始*/
do{
cout<<endl<<"您现在可以开始输入这两个整数:"<<endl;

cout<<"第一个:";
/*输入第一个数并对输入进行检测*/
while(1)
{
cg=1;
gets(num1);
for(int i=0;i<20;i++)
{
if(num1[i]>'9')/*如果有非数字*/
{
cout<<"输入无效,请重新输入:"<<endl;
cg=0;
break;
}
if(num1[i]=='-')
{
cout<<"暂时不讨论负数的公约数,请重新输入:"<<endl;
cg=0;
break;
}
}
if(cg==1)
{
n1=atoi(num1);
if(n1>0)
{
break;
}
else if(n1==0)
{
cout<<"“0”的公约数没有意义,请重新输入:";
}
}
else if(cg==0)
{
continue;
}
}/*小while循环结束*/

cout<<"第二个:";
/*输入第二个数并对输入进行检测*/
while(1)
{
cg=1;
gets(num2);
for(int i=0;i<20;i++)
{
if(num2[i]>'9')/*如果有非数字*/
{
cout<<"输入无效,请重新输入:"<<endl;
cg=0;
break;
}
if(num2[i]=='-')
{
cout<<"暂时不讨论负数的公约数,请重新输入:"<<endl;
cg=0;
break;
}
}
if(cg==1)
{
n2=atoi(num2);
if(n2>0)
{
break;
}
else if(n2==0)
{
cout<<"“0”的公约数没有意义,请重新输入:";
}
}
else if(cg==0)
{
continue;
}
}/*小while循环结束*/

cout<<"根据算法1,这两个数的最大公约数是:"<<gcdFuctionOne(n1,n2)<<endl;
cout<<"根据算法2,这两个数的最大公约数是:"<<gcdFuctionTwo(n1,n2)<<endl;
cout<<"根据算法3,这两个数的最大公约数是:"<<gcdFuctionThree(n1,n2)<<endl;

cout<<endl<<"您的要求已经完成,"<<endl<<"您现在可以选择:1.继续输入下一组数据; 2.退出程序"<<endl;
cout<<"小提示:如果您输入的不是1或2,程序将处于等待状态直到您输入1或2"<<endl;
cout<<"请选择(输入数字'1'或'2'): ";
while(1)
{
choice = getchar();
if(choice-'0'==1||choice-'0'==2)
{
break;
}
}
}while(choice-'0'==1);/*若用户选择为1,则继续循环*/

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: