求最大公约数的4种算法(C++)

一、实验目的
1.计算两个正整数的最大公约数和最小公倍数,并进行程序的调式与测试。
2.理解四种不同的求最大公约数的方法,学习其思维模式。
3.了解算法的概念。对问题的分析时,进行合适的算法设计。
二、算法设计
1.题目分析
(1)首先输入一对正整数,对两个数进行判断,若不是正整数,则给出提示并重新输入,直至两个数均为正整数为止。
(2)将两个数传入计算最大公约数的函数和计算最小公倍数的函数中,求解输出。
(3)验证各种算法的效率,在求解函数之前设置一个计时器开始运行,在函数执行完毕后,结束计时,计算出两个时间节点的差,即可得出每个函数执行一定次数的时间。规定统一的次数,将每种算法所用时间进行对比即可。
2.算法设计
1.辗转相除法,又称欧几里得算法。用于计算两个正整数a,b的最大公约数和最小公倍数,其依赖于gcd(a,b) = a (b=0)和gcd(b,a mod b) (b!=0).
2.穷举法,也叫枚举法,求最大公约数时从两者中较小的数开始,由大到小列举,直到找到第一个公约数为止。
3.更相减损法,若两个正整数都为偶数,则用2约简,直到不能约简为止。然后用大数减小数,将差与较小的数比较,再以大数减小数,直到减数和差相等为止。
4. Stein算法,两个数均为偶数时有公约数2,且公约数一定为偶数。一个奇数一个偶数时,因为其奇偶性的不同,所以其最大公约数一定为奇数。当两个数均为奇数时,其最大公约数一定是奇数。
三、业务流程图设计
欧几里得算法:


穷举法:


更相减损法:


Stein算法:


四、主要代码(2.0.0版)

/*********************************************************************************
*FileName:  Test1.cpp
*Author:  Qixiang.Su
*e-mail:  617992304@qq.com
*Version:  2.0.0
*Date:  2019.3.10
*Description: 求两个正整数的最大公约数和最小公倍数
*             理解各种算法求解过程
*History:
1.Date:    2019.3.10
Author:  Elf.苏洛曦
Modification:   Create  project
2.Date:    2019.3.12
Author: Elf.苏洛曦
Modification:   1.0.0版
3.Date:    2019.3.14
Author:  Elf.苏洛曦
Modification:   2.0.0版
**********************************************************************************/
#include<iostream>
#include<time.h>
using namespace std;int t1, t2, s, w;//辗转相除法求最大公约数函数
int divisor(int a, int b) {int temp;//比较两个数的大小,值大的数为a,值小的数为bif (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 divisor1(int a, int b) {int temp;temp = (a > b) ? b : a;   //求较小值while (temp > 0) {if (a % temp == 0 && b % temp == 0) {break;}else {temp--;}}return (temp);
}//穷举法求最小公倍数
int multiple1(int a, int b) {int p, q, temp;p = (a > b) ? a : b;  //求两数中的最大值q = (a > b) ? b : a;  //求两数中的最小值temp = p;while (1) {if (p % q == 0) {break;}else {p += temp;}}return (p);
}//更相减损法求最大公约数
int gcd1(int a, int b) {int i = 0, temp, x = 0;while (a % 2 == 0 && b % 2 == 0) {    //m,n有公约数2时a /= 2;b /= 2;i += 1;}//a,b的值互换if (a < b) {temp = a;a = b;b = temp;}while (x) {x = a - b;a = (b > x) ? b : x;   b = (b < x) ? b : x;if (b == (a - b)) {    //差和减数相等break;}}if (i == 0) {return b;}else {return (int)pow(2, i)*b;}
}//输入正整数
int setNumber() {int a;cout << "请输入正整数:" << endl;cin >> a;if (a <= 0) {cout << "您输入的数值不符合规范(要求:正整数)" << endl;setNumber();}else {return a;}
}//Stein算法函数非递归调用求最大公约数
int Stein(unsigned int x, unsigned int y) {int factor = 0;   //计数器int temp;//大数赋给x,小数赋给yif (x < y) {temp = x;x = y;y = temp;}if (0 == y) {return 0;}while (x != y) {if (x & 0x1) {if (y & 0x1) {   //x,y都为奇数y = (x - y) >> 1;x -= y;}else {    // x为奇数,y为偶数y >>= 1;}}else {if (y & 0x1) {   // x为偶数,y为奇数x >>= 1;if (x < y) {temp = x;x = y;y = temp;}}else {   //x,y均为偶数x >>= 1;y >>= 1;++factor;}}}return (x << factor);
}//Stein算法函数递归调用求最大公约数
int gcd2(int u, int v) {if (u == 0) {return v;}if (v == 0) {return u;}if (~u & 1) {if (v & 1) {return gcd2(u >> 1, v);}else {return gcd2(u >> 1, v >> 1) << 1;}}if (~v & 1) {return gcd2(u, v >> 1);}if (u > v) {return gcd2((u - v) >> 1, v);}return gcd2((v - u) >> 1, u);
}//获得两个正整数的最大公约数和最小公倍数
void getResult() {s = setNumber();w = setNumber();int count;cout << "请输入你想循环的次数:" << endl;cin >> count;clock_t strat = clock();for (int i = 0; i < count; i++) {t1 = divisor(s, w);t2 = multiple(s, w);}clock_t end = clock();cout << "辗转相除法函数嵌套调用所求结果:" << endl;cout << s << "和" << w << "的最大公约数为:" << t1 << endl;cout << s << "和" << w << "的最小公倍数为:" << t2 << endl;cout << "运行" << count << "次所花时间为:" << end - strat << "毫秒"<<endl;cout << endl;clock_t strat1 = clock();for (int i = 0; i < count; i++) {t1 = gcd(s, w);t2 = multiple(s, w);}clock_t end1 = clock();cout << "辗转相除法函数递归调用所求结果:" << endl;cout << s << "和" << w << "的最大公约数为:" << t1 << endl;cout << s << "和" << w << "的最小公倍数为:" << t2 << endl;cout << "运行" << count << "次所花时间为:" << end1 - strat1 << "毫秒" << endl;cout << endl;clock_t strat2 = clock();for (int i = 0; i < count; i++) {t1 = divisor1(s, w);t2 = multiple1(s, w);}clock_t end2 = clock();cout << "穷举法所求结果:" << endl;cout << s << "和" << w << "的最大公约数为:" << t1 << endl;cout << s << "和" << w << "的最小公倍数为:" << t2 << endl;cout << "运行" << count << "次所花时间为:" << end2 - strat2 << "毫秒" << endl;cout << endl;clock_t strat3 = clock();for (int i = 0; i < count; i++) {t1 = gcd(s, w);t2 = multiple(s, w);}clock_t end3 = clock();cout << "更相减损法所求结果:" << endl;cout << s << "和" << w << "的最大公约数为:" << t1 << endl;cout << s << "和" << w << "的最小公倍数为:" << t2 << endl;cout << "运行" << count << "次所花时间为:" << end3 - strat3 << "毫秒" << endl;cout << endl;clock_t strat4 = clock();for (int i = 0; i < count; i++) {t1 = Stein(s, w);t2 = multiple(s, w);}clock_t end4 = clock();cout << "Stein算法非递归调用所求结果:" << endl;cout << s << "和" << w << "的最大公约数为:" << t1 << endl;cout << s << "和" << w << "的最小公倍数为:" << t2 << endl;cout << "运行" << count << "次所花时间为:" << end4 - strat4 << "毫秒" << endl;cout << endl;clock_t strat5 = clock();for (int i = 0; i < count; i++) {t1 = gcd2(s, w);t2 = multiple(s, w);}clock_t end5 = clock();cout << "Stein算法递归调用所求结果:" << endl;cout << s << "和" << w << "的最大公约数为:" << t1 << endl;cout << s << "和" << w << "的最小公倍数为:" << t2 << endl;cout << "运行" << count << "次所花时间为:" << end5 - strat5 << "毫秒" << endl;cout << endl;}int main() {getResult();system("pause");
}

五、调试和测试
1.在1.0.0版本中
一次进行测试,出现了错误,如下图:

在编译时没有错误,在运行过程也无错误,在结果中,穷举法的结果与其他的不同。对穷举法进行单独测试,结果如下:

与实际不符,结果也是错误的,通过逐语句调试

发现求最大公约数中temp的值存在异常,通过仔细检查,将while(temp > 0)写成了while(temp = 0),嵌套出现了层次错误。改正后,运行结果如下:


最大公约数正确,最小公倍数错误,对求最小公倍数的函数进行逐语句后

p和q的值相同,存在错误,仔细检查后发现将(a>b)写成了(a<b),改正过后,结果均正确,如下图:

2. 2.0.0版本
在2.0.0版本中取消了1.0.0版本中的输入要求数的对数,增加了对一组数据想要循环次数的输入,这样免去了测试时手动输入多组数据的程序。

通过监视,查看各个变量的变化情况,如下图:

(1) 输入两个正整数15和9,执行求解代码100000次,比较各种算法的速度,结果如下图:

从结果可以看出Stein算法非递归比较快,数字较小时,穷举法所用时间也比较短。

(2)输入两个正整数143和345,执行求解代码100000次,比较各种算法的速度,结果如下图:

在数字较大时且函数循环次数较多之后,Stein算法的执行速度还是很快,而穷举法需要的时间大幅度增长,其他几种算法的时间相差不大。
(3)输入两个正整数12和8,执行求解代码100000次,比较各种算法的速度,结果如下图:

数字较小时,穷举法的优势还是很明显,执行速度优于其他几种算法。
同时通过上面的几组测试发现,非递归的速度要优于递归。
六、总结
通过本次实验,学习到了求最大公约数几种常见的算法,对算法也有了一定的认识。也领略到了算法的思维的精妙之处。在上机过程中也出现了一些错误,通过逐步调试也解决了问题。在程序上,还存在一些缺陷,在进行速度的测试时,仅用一组数据的循环次数来判断,这种情况下,就忽略了手动输入数据时数据的复杂性。在输入正整数时仅对数字的正负性进行了判断,而对于其他会出现异常的情况,如在输入数字时误输入字母、符号等,未进行处理。没有通过正则表达式来判断输入,也未将异常进行捕捉和抛出。所以要学习的设计方法还有很多,只有学习到更多的处理方法,才能让自己的程序更具健壮性。

求最大公约数的4种算法(C++)相关推荐

  1. 最大公约数简便算法_求最大公约数的4种算法

    for(z=0; z<10000000; z++) 循环只是为了增加程序的运行时间, 让我们体会算法的时间复杂度. 算法一:短除法 想法,采用短除法找出2个数的所有公约数,将这些公因子相乘,结果 ...

  2. 最大公约数简便算法_求最大公约数的几种算法

    给定两个整数,求出这两个整数的最大公约数是我们从小就接触过的问题,但是我们如何用更简洁的算法来计算呢? 本文中,假定这两个整数是m和n且m>=n>=0.让我们从最简单的算法说起! 一.Co ...

  3. 求最大公约数的几种算法

    求两个数的最大公约数是生活中常见的运算.我们普遍知道的有欧几里得法.穷举法,其实还有其它方法:更相减损法.下面面一起来看看: 1.辗转相除法,又叫欧几里得法: int f1(int n1, int m ...

  4. 求最大公约数的四种算法

    一. 题目分析 如果有一个自然数a能被自然数b整除,则称a为b的倍数,b为a的约数.几个自然数公有的约数,叫做这几个自然数的公约数.公约数中最大的一个公约数,称为这几个自然数的最大公约数. 根据约数的 ...

  5. java 求最大公因数_求最大公约数的三种算法(java实现)

    三种算法: //欧几里得算法(辗转相除): public static int gcd(int m,int n) { if(m int k=m; m=n; n=k; } //if(m%n!=0) { ...

  6. 打卡第二十四天(问题:计算阶乘,打印九九乘法表,计算最大公约数的两种算法)

    1.计算阶乘 这里给出递归和递推两种计算阶乘的程序. #include<stdio.h> //递归法计算阶乘 long factorial(int n) {if(n==0||n==1)re ...

  7. c语言实现求最大公约数的三种方法

    一.最大公约数 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约数记为(a,b,c),多个整数的最大公约数也 ...

  8. 求最大公约数的4种方法

    一.最大公约数与最小公倍数 最大公约数,属于数论所探究的内容. 最大公约数可以通过下面的三种方法求出来. 最小公倍数呢,它与最大公约数的乘机为所求数之积. 比如求 x,y的最大公约数和最小公倍数 记住 ...

  9. java 直线交点_[Java教程]谈谈求线段交点的几种算法(js实现,完整版)

    [Java教程]谈谈求线段交点的几种算法(js实现,完整版) 0 2014-08-27 10:05:22 "求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面 ...

最新文章

  1. 关于子元素的margin-top对父级容器无效
  2. 接口中不能有方法体吗-------不是
  3. 用js控制选择CheckBoxList
  4. 比较好的一些 ConcurrentHashMap讲解博客
  5. beego原生mysql查询_Beego基础学习(五)Golang原生sql操作Mysql数据库增删改查(基于Beego下测试)...
  6. 8道python练习题,能做出来的没几个
  7. 笔记本windows7设置WIFI教程(超详细)
  8. windows10下安装JDK及环境变量设置
  9. txt格式转换成prg_用批处理打印磁盘上所有的.PRG文件
  10. 【STM32 .Net MF开发板学习-16】Zigbee遥控智能小车
  11. 删除查找后的目录或文件
  12. 符合c语言语法规定的表达式,若变量定义为int fahr;,则5(fahr-32)/9是符合C语言语法的表达式...
  13. SQL Server 2005 Service Pack 4 下载地址
  14. 5.3 数据通路-专用通路
  15. 使用BoundsChecker检测内存泄漏
  16. 推荐一款HTML在线编辑器
  17. 初学Android,图形图像之使用Canvas,Paint绘图(二十五)
  18. C#语言实例源码系列-虚拟键盘
  19. java pdfreader去除水印_Java - PDF操作库 ItextPdf和PdfBox添加水印
  20. 【记录】初探FRP+云服务器实现端口映射(2020.7.27)

热门文章

  1. 二十三、正则表达式中的“r”含义
  2. 将一个给定的整数插到原本有序的整数序列中,使结果序列仍然有序。
  3. DOS控制台及其常用命令
  4. android定位附近店铺,高德地图怎么添加店铺位置_高德地图定位怎么设置添加自己家店铺位置_攻略...
  5. win10多用户同时远程桌面登陆(允许多个RDP会话)-支持win10最新1909版2004版
  6. 教你修改电脑mac地址图解教程
  7. HTML中添加点击链接 进行Skype、QQ、微信对话的问题
  8. 计算机期末考试质量分析报告,信息技术期末考试质量分析
  9. 四年级计算机教学目的,四年级计算机教学计划
  10. 半角和全角的区别 java_全角和半角区别