一、实验名称:求2个数的最大公约数
二、实验内容:利用辗转相除法、更相损减法、穷举法、Stein算法求两个数的最大公因数。并且比较这四种算法的运行时间。
三、算法设计和代码部分
1、辗转相除法
辗转相除法(又名欧几里德法)C语言中用于计算两个正整数a,b的最大公约数和最小公倍数,实质它依赖于下面的定理:
a b=0

gcd(a,b) =

gcd(b,a mod b) b!=0
其算法过程为: 前提:设两数为a,b设其中a 做被除数,b做除数,c为余数
1、大数放a中、小数放b中;
2、求a/b的余数;
3、若c=0则b为最大公约数;
4、如果c!=0则把b的值给a、c的值给a;
5、返回第二步;
代码:
#include<stdio.h>
int main()
{
int a=0;
int b=0;
int c=0;
printf(“辗转相除法\n”);
printf(“请输入第一个数:\n”);
scanf("%d",&a);
printf(“请输入第二个数:\n”);
scanf("%d",&b);

while(a%b!=0)
{c=a%b;a=b;b=c;
}
printf("最大公约数为%d",b);
return 0;

}
辗转相除法算法流程图:

2、更相损减法
更相减损术,是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。《九章算术》是中国古代的数学专著,其中的“更相减损术”可以用来求两个数的最大公约数,即“可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。”
翻译成现代语言如下:
第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。所以更相减损法也叫等值算法。

代码:
#include<stdio.h>
#include<math.h>
int main()
{
int a=0;
int b=0;
int c=0;
int i=0;
printf(“求两个数的最大公约数\n”);
printf(“请输入第一个数的值:\n”);
scanf("%d",&a);
printf(“请输入第二个数的值:\n”);
scanf("%d",&b);

while(a!=b)
{while(a%2==0&&b%2==0){a=a/2;b=b/2;i++;}if(a>b) c=a-b;else c=b-a;a=b;b=c;
}
a=a*pow(2,i);
printf("这两个数的最大公约数是%d",a);return 0;

}
更相损减法算法流程图:

3、穷举法
穷举法(也叫枚举法)穷举法求两个正整数的最大公约数的解题步骤:从两个数中较小数开始由大到小列举,直到找到公约数立即中断列举,得到的公约数便是最大公约数 。
代码:
#include<stdio.h>

int way(int a,int b)
{
int c;
if(a<b)
{
c=a;
a=b;
b=c;
}
else c=b;
while(c>0)
{
if(a%c0&&b%c0) break;
else c–;
}
return ©;
}

int main()
{
int m,n,v;
printf(“请输入两个数的值:\n”);
scanf("%d%d",&m,&n);
v=way(m,n);
printf("\n这两个数的最大公因数是:\n%d\n",v);
return 0;
}
穷举法算法流程图:

4、Stein算法
Stein算法由J. Stein 1961年提出,这个方法也是计算两个数的最大公约数。来研究一下最大公约数的性质,发现有 gcd( kx,ky ) = kgcd( x,y ) 这么一个非常好的性质。试取 k=2,则有 gcd( 2x,2y ) = 2 * gcd( x,y )。很快联想到将两个偶数化小的方法。那么一奇一个偶以及两个奇数的情况如何化小呢?
先来看看一奇一偶的情况: 设有2x和y两个数,其中y为奇数。因为y的所有约数都是奇数,所以 a = gcd( 2x,y ) 是奇数。根据2x是个偶数不难联想到,a应该是x的约数。我们来证明一下:(2x)%a=0,设2x=n
a,因为a是奇数,2x是偶数,则必有n是偶数。又因为 x=(n/2)*a,所以 x%a=0,即a是x的约数。因为a也是y的约数,所以a是x和y的公约数,有 gcd( 2x,y ) <= gcd( x,y )。因为gcd( x,y )明显是2x和y的公约数,又有gcd( x,y ) <= gcd( 2x,y ),所以 gcd( 2x,y ) = gcd( x,y )。至此,我们得出了一奇一偶时化小的方法。
再来看看两个奇数的情况:设有两个奇数x和y,不妨设x>y,注意到x+y和x-y是两个偶数,则有 gcd( x+y,x-y ) = 2 * gcd( (x+y)/2,(x-y)/2 ),那么 gcd( x,y ) 与 gcd( x+y,x-y ) 以及 gcd( (x+y)/2,(x-y)/2 ) 之间是不是有某种联系呢?为了方便设 m=(x+y)/2 ,n=(x-y)/2 ,容易发现 m+n=x ,m-n=y 。设 a = gcd( m,n ),则 m%a=0,n%a=0 ,所以 (m+n)%a=0,(m-n)%a=0 ,即 x%a=0 ,y%a=0 ,所以a是x和y的公约数,有 gcd( m,n )<= gcd(x,y)。再设 b = gcd( x,y )肯定为奇数,则 x%b=0,y%b=0 ,所以 (x+y)%b=0 ,(x-y)%b=0 ,又因为x+y和x-y都是偶数,跟前面一奇一偶时证明a是x的约数的方法相同,有 ((x+y)/2)%b=0,((x-y)/2)%b=0 ,即 m%b=0 ,n%b=0 ,所以b是m和n的公约数,有 gcd( x,y ) <= gcd( m,n )。所以 gcd( x,y ) = gcd( m,n ) = gcd( (x+y)/2,(x-y)/2 )。
整理一下,对两个正整数 x>y :
1.均为偶数 gcd( x,y ) =2gcd( x/2,y/2 );
2.均为奇数 gcd( x,y ) = gcd( (x+y)/2,(x-y)/2 );
2.x奇y偶 gcd( x,y ) = gcd( x,y/2 );
3.x偶y奇 gcd( x,y ) = gcd( x/2,y ) 或 gcd( x,y )=gcd( y,x/2 );
代码:
#include<stdio.h>
#include<stdio.h>

int gcd(int u,int v)
{
if (u == 0) return v;
if (v == 0) return u;
// look for factors of 2
if (~u & 1) // u is even
{
if (v & 1) // v is odd
return gcd(u >> 1, v);
else // both u and v are even
return gcd(u >> 1, v >> 1) << 1;
}
if (~v & 1) // u is odd, v is even
return gcd(u, v >> 1);
// reduce larger argument
if (u > v)
return gcd((u - v) >> 1, v);
return gcd((v - u) >> 1, u);
}

int main()
{
int a=0;
int b=0;
int c=0;
printf(“求两个数的最大公约数\n”);
printf(“请输入第一个数的值:\n”);
scanf("%d",&a);
printf(“请输入第二个数的值:\n”);
scanf("%d",&b);
c=gcd(a,b);
printf("\n最大公约数为%d\n",c);
return 0;
}
算法流程图:

本次实验

,一共是4个算法。我先接触时,是先思考各种方法如何解决这个问题的。通过上机说明和百度搜索,我先后理解辗转相除法和更相损减法,并且将这两个算法的流程图画好。并且在用代码实现自己的流程图时,感觉十分的流畅。
但是我在穷举法这却出现了问题。穷举法的思维很简单,所以我没有先画流程图,但是在用代码实现这个问题的时候,我发现我的代码总会出现一个问题:
Linking…
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/123.exe : fatal error LNK1120: 1 unresolved externals
执行 link.exe 时出错.

123.exe - 1 error(s), 0 warning(s)
目前问题还没解决,代码参考了上机说明,我会进一步把问题搞清楚。关于stein算法,刚开始理解是用于优化,最后还得靠前三种方法解决,但是代码无法理解,还得继续思考这个问题。

4种方法求2个数公因数相关推荐

  1. 三种方法求两个数最大公因数

    1.题目描述: 求两个正整数的最大公约数和最小公倍数. 基本要求:1.程序风格良好(使用自定义注释模板),两种以上算法解决最大公约数问题,提供友好的输入输出. 提高要求:1.三种以上算法解决两个正整数 ...

  2. 三种方法求最大公约数及求n个数的最小公倍数

    一.三种方法求两个数的最大公约数 (1) 辗转相除法 辗转相除法求最大公约数是一种常用的求两个数的最大公约数的方法. 方法是: 以小数除大数,如果能整除,那么小数就是所求的最大公约数.否则就用余数来除 ...

  3. 【数学知识】三种方法求 [1,n] 中所有数欧拉函数(线性筛欧拉函数优化至 O(n) )

    整理的算法模板合集: ACM模板 ①直接求小于或等于n,且与n互质的数个数(求[1,n]中所有数的欧拉函数时间复杂度:O(nn)O(n\sqrt{n})O(nn​)) ②求[1,n]之间每个数的质因数 ...

  4. C++算法:三种方法求最大公约数和最小公倍数

    三种方法求最大公约数和最小公倍数标题 首先明确最大公约数和最小公倍数的关系,设两个数为a,b:最大公约数为c,最大公倍数为d: 则ab=cd;怎么得到的可以通过数学算式证明. 分别用暴力搜索法,辗转相 ...

  5. C语言四种方法求最大公约数

    一.实验要求 运行最大公约数的常用算法,并进行程序的调试与测试,要求程序设计风格良好,并添加异常处理模块. 二.实验方法(四种) 1.辗转相除法(欧几里德法) C语言中用于计算两个正整数a,b的最大公 ...

  6. Python两种方式求多个数的最大公因数(HCF)和最小公倍数(LCM)

    Python两种方式求多个数的最大公因数(HCF)和最小公倍数(LCM) 最大公因数 1. 列表排序 2. 将列表分为两部分 3. 求最大公因数的质因子 4. 得到结果 5. 完整程序 最小公倍数 另 ...

  7. 三种方法求最大公约数(C语言版)

    问题描述:用三种方法求两个的整数的最大公约数. 算法分析: 1.相减法:输入两整数a和b,(1)如果a>b,a=a-b;(2)如果a<b,b=b-a;(3)如果a=b,a或b就为这两个整数 ...

  8. KMP-两种方法求next数组

    文章目录 前言 最佳最快方法 原理 方法详述 分析和思考 其他的next数组 总结 最好理解记忆方法 原理 前缀字符串和后缀字符串 部分匹配值 next数组意义 方法详述 转化 思考 测试链接 前言 ...

  9. 机器学习中的矩阵求导的一点总结(三种方法求线性回归最佳参数)

    机器学习中的矩阵求导的一点总结(三种方法求线性回归最佳参数) 转载于:https://blog.csdn.net/promisejia/article/details/80159619?ops_req ...

最新文章

  1. python 中将大列表拆分成小列表
  2. Java Virtual Machine Stacks(虚拟机栈)
  3. io流图解 java_详细讲解JAVA中的IO流
  4. spring一站式开发_Spring开发人员知道的一件事
  5. 反馈电路中相位补偿,到底是什么鬼?
  6. linux mysql connector_fd_在CentOS里使用MySQL Connector/C++
  7. DataGrid 导出到 Excel 的帮助类
  8. 【XNA4.0】动画
  9. ping不同的网卡方法
  10. 看了这个视频都想辞职了
  11. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_05 IO字符流_9_JDK7和JDK9流中异常的处理...
  12. 单播、多播(组播)和广播解释
  13. HDU_6078 Wavel Sequence
  14. 用光盘怎样重装电脑系统
  15. 夜明け前より瑠璃色な 攻略
  16. Android实现自定义铃音
  17. mysql lucene 结合_Lucene基础(四)-- 结合数据库使用
  18. 三星手机打不开php文件,三星手机将支持完整版Linux
  19. opencv-12-高斯滤波-双边滤波(附C++代码实现)
  20. 文件处理与垃圾回收机制

热门文章

  1. A Game of Thrones(79)
  2. RRAM:走向新型嵌入式存储之路
  3. 稳压二极管、整流二极管、开关二极管
  4. 基于深度学习和单目摄像头测距的前车碰撞预警源码
  5. python canvas画弧度_趣玩 Python 之绘制基本图形
  6. Django ckeditor自定义表情包
  7. AD的pcb中高度规则设置
  8. php网页设计心得,网页设计心得体会
  9. 装上 Ubuntu 13.04 之后风扇很吵的解决办法
  10. 飞机大战小游戏源码---飞机大战初体验