引入
求两个非负整数的最大公约数和最小公倍数?
最大公约数
最大公约数百度百科:
最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约数记为(a,b,c),多个整数的最大公约数也有同样的记号。求最大公约数有多种方法,常见的有质因数分解法、短除法、辗转相除法、更相减损法。与最大公约数相对应的概念是最小公倍数,a,b的最小公倍数记为[a,b]。
最小公倍数百度百科
最小公倍数百度百科:
两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。整数a,b的最小公倍数记为[a,b],同样的,a,b,c的最小公倍数记为[a,b,c],多个整数的最小公倍数也有同样的记号。
与最小公倍数相对应的概念是最大公约数,a,b的最大公约数记为(a,b)。关于最小公倍数与最大公约数,我们有这样的定理:(a,b)x[a,b]=ab(a,b均为整数)。
分析
求最大公约数和最小公倍数是由方法的,如果说12、8的最大公约数我们一看就知道是4,12、8的最小公倍数一看就是24。写程序不是一看就能写出来,我们需要从中找出算法,将算法写在程序中,常见的算法由辗转相除法、更相减损发、质因数分解法、短除法
- 辗转相除法、更相减损术求的是最大公约数,最小公倍数:a*b/最大公约数
辗转相除法
每种算法的核心不一样,拿辗转相除法,怎么求最大公约数、最小公倍数:
最大公约数
-
比较出两数的大小
-
大数%小数求余,小数赋值给之前的大数,余数赋值给小数
-
当余数等于0结束
最小公倍数
-
两数相乘/最大公约数
我们要做的是把算法的逻辑写入程序
c
# include <stdio.h>
//声明最大公约数函数
//int test1(a,b);
//声明最小公倍数函数
//int test2(a,b);
int main()
{
//首先需要两数
int a,b;
//输入两数
scanf("%d%d",&a,&b);
//调用求最小公倍数函数 ,将a、b两个值传递过去
test2(a,b);
return 0;
}
//最大公约数是int,把函数返回值类型设置为int
int test1(a,b) {
/**
两数的最大公约数和最小公倍数
最大公约数举个例子(12、8 的最大公约数是4)
最小公倍数举个例子(12、8 的最小公倍数是24)
*/
//网上有很多算法求最大公约数和最小公倍数 ,每种算法的核心不一样
/**
辗转相除法
1.比较出两数的最大值
2. 大数%小数求余,小数赋值给之前的大数,余数赋值给小数
3.当余数位0结束
*/
//自定义a必须大于b,定义一个中间变量
int t;
if(a<b){
t = a;
a = b;
b = t;
}
//循环求余数,当小数b也就是余数等于0,就结束循环
while(b!=0){
t=a%b;
a = b;
b = t;
}
printf("最大公约数:%d\n",a);
return a;
}
//最小公倍数是一个int类型,把返函数回值类型设置为int
int test2(int a, int b) {
//定义变量接收最大公约数
int t = test1(a,b);
//打印最小公倍数
printf("最小公倍数:%d\n",a*b/t);
//根据两数相乘除以最大公约数,获得最小公倍数
return a*b/t;
}
为了方便记忆,通过余数,找到最大公约数
更相减损术
更相减损术百度百科
更相减损术是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。
九章算法百度百科
《九章算法比类大全》是明代吴敬撰写的算书,亦名《九章详注比类算法大全》。明代前期的算书,十卷首一卷,成书于1450年。
理解:
没想到明代都有算法一说,中国在明代还是比较繁荣的。更相减损术是出自《九章算术》的一种求最大公约数的算法
- 判断传入的两数是否都是偶数例如a、b
- 如果
a%b==0
,最大公约数是b a/=2、 b/=2 当while(a%2==0 && b%2==0)
错误结束条件 使用2约减,使用循环判断约减了几次,最大公约数是 约减次数*2
- 如果
- 如果传入的两数不为偶数,使用简损法,自定义a必须大于b,定义转换变量
t,t=a-b、a=b>t?b:t、b=b<t?b:t,结束条件是(t == (a-b))
,返回最大公约数是b的值
c
# include <stdio.h>
//声明最小公倍数
int test2(a,b);
//声明最大公约数函数
int test3(a,b);
int main()
{
//首先需要两数
int a,b;
//输入两数
scanf("%d%d",&a,&b);
printf("最大公约数:");
printf("%d\n",test3(a,b));
//调用更相减损法求最小公倍数
printf("最小公倍数:") ;
printf("%d",test2(a,b));
return 0;
}
//更相减损法求最大公约数函数
int test3(int a,int b) {
/**
1、判断传入的两数是否都是偶数例如a、b
如果a%b==0,最大公约数是b
a/=2、 b/=2 当while(a%2==0 && b%2==0)`错误结束条件 使用2约减,使用循环判断约减了几次,最大公约数是 约减次数*2
2、如果传入的两数不为偶数,使用简损法,自定义a必须b,定义转换变量t,t=a-b、a=b>t?b:t、b=b<t?b:t,结束条件是(t == (a-b))
*/
int i = 0,t;
//a%b==0,最大公约数是b
if(a%b==0){
return b;
}
//a/=2、 b/=2 当while(a%2==0 && b%2==0)`错误结束条件 使用2约减,使用循环判断约减了几次,最大公约数是 约减次数*2
else if(a%2==0 && b%2==0){
while(a%2==0 && b%2==0){
a/=2;
b/=2;
i++;
}
return i*2;
}
//如果传入的两数不为偶数,使用简损法,自定义a必须b,定义转换变量t,t=a-b、a=b>t?b:t、b=b<t?b:t,结束条件是(t == (a-b)),返回最大公约数是b的值
else{
//自定义a必须大于b
if(a<b){
t = a;
a = b;
b = t;
}
while(1){
t=a-b;
a=b>t?b:t;
b=b<t?b:t;
if(b==(a-b)){
break;
}
}
//返回最大公约数是b的值
return b;
}
}
//最小公倍数是一个int类型,把返函数回值类型设置为int
int test2(int a, int b) {
//定义变量接收最大公约数
int t = test3(a,b);
//根据两数相乘除以最大公约数,获得最小公倍数
return a*b/t;
}
为了方便记忆,更相减损法,记住一点,它是通过差值找最大公约数
穷举法
百度百科
穷举法就是枚举法,在进行归纳推理时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么这结论是可靠的,这种归纳方法叫做枚举法.
理解:
穷举法有点像,我们直接从两数中看出最大公约数和最小公倍数。而计算机这是通过循环去一个个比对出来。
-
从两数中最小的数开始找,直到找到符合条件的数,
a%t==0 && b%t==0
递减(最大公约数) -
从最大值的倍数开始找,找到符合条件的值
t%b==0
递增(最小公倍数)这里的t是开始找的初始值,a、b是两个数
# include <stdio.h>
//声明最小公倍数
int test4(a,b);
//声明最大公约数函数
int test5(a,b);
int main()
{
//首先需要两数
int a,b;
//输入两数
//穷举法求最大公约数,最小公倍数
scanf("%d%d",&a,&b);
printf("最大公约数:");
printf("%d\n",test4(a,b));
printf("最小公倍数:") ;
printf("%d",test5(a,b));
return 0;
}
//定义最大公约数函数
int test4(int a, int b) {
//定义转换变量
int t;
//找出最小值
t = (a>b)?b:a;
while(1){
if(a%t==0 && b%t==0) {
break;
}
//从两数中最小的数开始找,直到找到符合条件的数,递减
t--;
}
//返回最大公约数
return t;
}
//定义最小公倍数函数
int test5(int a,int b){
//定义变量作为中间转换变量
int t;
//自定义a>b
a=a>b?a:b;
b=a<b?a:b;
//把最大值赋给转换变量
t = a;
//当找出一个符合最小公倍数的值结束循环
while(1) {
if(t%b==0){
break;
}
//从两数中最大数的倍数开始找,直到找到符合条件的数,递增
t+=a;
}
//返回最小公倍数
return t;
}
方便记忆:
最大公约数,通过两数中的小的数,递减找出最大公约数
最小公倍数,通过最大数的倍数递增,找出最小公倍数