求最大公约数之辗转相除法、更相减损术及两者结合算法
来源:互联网 发布:景泰蓝 珐琅 区别 知乎 编辑:程序博客网 时间:2024/06/05 00:23
下面代码受漫画算法:辗转相除法是什么鬼?启发,原文讲解十分精彩,强烈建议查看原文,但是原文代码有几个小错误,本文代码为修改后的版本。讲解均在代码注释。
/**< 测试几种求最大公约数的算法 */#include <stdio.h>#include <stdlib.h>int gcdOri(const int a, const int b);int gcdEA(const int a, const int b);int gcdMD(const int a, const int b);int gcdBEST(const int a, const int b);int main(){ int a, b; scanf("%d %d", &a, &b); printf("Common algorithm: %d\n", gcdOri(a, b)); printf("Euclidean algorithm: %d\n", gcdEA(a, b)); printf("More derogation algorithm: %d\n", gcdMD(a, b)); printf("Best algorithm: %d\n", gcdBEST(a, b)); printf("Hello world!\n"); system("pause");}/** 最暴力的算法,从2遍历到a和b中较少的那个一半 * 效率最低,时间复杂度为O(n/2); */int gcdOri(const int a, const int b){ int smallnum = a<b?a:b; int bignum = a>b?a:b; int i, rlt; if(bignum%smallnum == 0) rlt = smallnum; else { for(i=2; i<=smallnum/2; i++) { if((bignum%i==0) && (smallnum%i==0)) { rlt = i; } } } return rlt;}/** 辗转相除法, 又名欧几里得算法(Euclidean algorithm) * 定理:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。 * 比如10和25,25除以10商2余5,那么10和25的最大公约数,等同于10和5的最大公约数。 * 但是当a、b较大是,a%b取模运算的性能比较低 */int gcdEA(const int a, const int b){ int rlt; int smallnum = a<b?a:b; int bignum = a>b?a:b; if(bignum%smallnum == 0) rlt = smallnum; else { rlt = gcdEA(smallnum, bignum%smallnum); } return rlt;}/** 更相减损术, 出自于中国古代的《九章算术》 * 两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。 * 比如10和25,25减去10的差是15,那么10和25的最大公约数,等同于10和15的最大公约数。 * 更相减算术依靠两数求差的方式来递归,运算的次数肯定远大于辗转相除法的取模方式 * 比如计算1000和1,就要递归999次 */int gcdMD(const int a, const int b){ int rlt; int smallnum = a<b?a:b; int bignum = a>b?a:b; if(bignum%smallnum == 0) /**< 应该和bignum==smallnum一样 */ rlt = smallnum; else { rlt = gcdMD(smallnum, (bignum-smallnum)); } return rlt;}/** 最优方法:把辗转相除法和更相减损法的优势结合起来,在更相减算术的基础上使用移位运算 * 对于给定的正整数a和b,不难得到如下的结论。其中gcb(a,b)的意思是a,b的最大公约数函数: * 当a和b均为偶数,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1) * 当a为偶数,b为奇数,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b) * 当a为奇数,b为偶数,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1) * 当a和b均为奇数,利用更相减损术运算一次,gcb(a,b) = gcb(b, a-b), 此时a-b必然是偶数,又可以继续进行移位运算。 */int gcdBEST(const int a, const int b){ int rlt = 0; int smallnum = a<b?a:b; int bignum = a>b?a:b; if(bignum%smallnum == 0) rlt = smallnum; else { if(!(bignum&1) && !(smallnum&1)) /**< '&1'与1运算,就是2进制下末尾和1做‘与’运行,结果同1异0,所以可用来判断奇偶,返回1为奇,0为偶 */ { rlt = gcdBEST(bignum>>1, smallnum>>1) << 1; /**< 右移运算 >>1 相当于偶数/2,相反地,左移运算,相当于*2 */ } else if(!(bignum&1) && smallnum&1) { rlt = gcdBEST(bignum>>1, smallnum); } else if(bignum&1 && !(smallnum&1)) { rlt = gcdBEST(bignum, smallnum>>1); } else if(bignum&1 && smallnum&1) { rlt = gcdBEST(smallnum, bignum-smallnum); } } return rlt;}
阅读全文
0 0
- 求最大公约数之辗转相除法、更相减损术及两者结合算法
- 求最大公约数-辗转相除法-更相减损术
- 辗转相除法+更相减损法求最大公约数
- 求最大公约数——辗转相除法,更相减损术
- C++算法:辗转相除法与更相减损术
- 最大公约数(辗转相除法和更相减损法)
- 辗转相除法、更相减损法、Stein算法
- 【C语言】最大公约数(更相减损法)和(辗转相除法)
- 欧几里德算法(辗转相除法) 求最大公约数
- 欧几里得算法 --- 辗转相除法求最大公约数
- 求最大公约数-辗转相除法-欧几里德算法
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- 求最大公约数-辗转相除法
- 辗转相除法求最大公约数
- 辗转相除法求最大公约数
- RecyclerView瀑布流
- Leetcode141. Linked List Cycle
- 基于onvif协议的视频监控系统(一):需要理解的关键字
- ubuntu 默认防火墙安装、启用、查看状态
- (转载)Android酷炫实用的开源框架(UI框架)
- 求最大公约数之辗转相除法、更相减损术及两者结合算法
- 基于时延的mptcp的拥塞控制
- LTE带宽和子载波计算方式
- 如何用74HC595实现流水灯
- 获得时间戳转为北京时间
- 拆分单循环链表
- 【python练习】 xlwt 操作excel 写入list数据并考虑合并单元格
- sed删除连续空白行
- dubbo学习过程、使用经验分享及实现原理简单介绍