C语言求最大公约数及最小公倍数
1. 最大公约数
1.1 定义
最大公约数(Greatest Common Divisor,GCD),也称最大公因数、最大公因子,是一种数学概念,指两个或多个整数共有约数中最大的一个。
1.2 解法一:常规法(暴力法)
1.2.1 定义
由于最大公约数的本质是一个最大的能同时被两整数整除的自然数。所以我们先比较两数大小,从较大数开始向上递增,直到找到那个最小公倍数。
1.2.2 代码实现
int gcd4(int a, int b)
{
//首先找到两个数中较大的数,用a存储较大数
if (a < b)
{
int temp = a;
a = b;
b = temp;
}
//从较大数开始寻找符合条件的最大公约数
for (int i = a; i > 0; --i)
{
if (a % i == 0 && b % i == 0)
{
return i;
}
}
}
1.3 解法二:辗转相除法(欧几里德法)
1.3.1方法解释:
用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。
1.3.2实例:
例如,求(319,377):
∵ 319÷377=0(余319)
∴(319,377)=(377,319);
∵ 377÷319=1(余58)
∴(377,319)=(319,58);
∵ 319÷58=5(余29)
∴ (319,58)=(58,29);
∵ 58÷29=2(余0)
∴ (58,29)= 29;
∴ (319,377)=29。
1.3.3 代码实现
/** * 递归版辗转相除法 * @param a * @param b * @return */
int gcd1(int a, int b)
{
if (a % b == 0)
{
return b;
}
else
{
return gcd1(b, a % b);
}
}
/** * 非递归辗转相除法求解最大公约数 * @param a * @param b * @return */
int gcd2(int a, int b)
{
while (b != 0)
{
int temp = a % b;
a = b;
b = temp;
}
return a;
}
1.4 解法二:更相减损法
1.4.1 方法解释:
(如果需要对分数进行约分,那么)可以折半的话,就折半(也就是用2来约分)。如果不可以折半的话,那么就比较分母和分子的大小,用大数减去小数,互相减来减去,一直到减数与差相等为止,用这个相等的数字来约分,这个数就是最大公约数;
1.4.2 步骤:
第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
则第一步中约掉的若干个2的积与第二步中等数的乘积就是所求的最大公约数。
1.4.3 实例:
- 用更相减损术求98与63的最大公约数。
解:由于63不是偶数,把98和63以大数减小数,并辗转相减:
98-63=35
63-35=28
35-28=7
28-7=21
21-7=14
14-7=7
所以,98和63的最大公约数等于7。
- 用更相减损术求260和104的最大公约数。
解:由于260和104均为偶数,首先用2约简得到130和52,再用2约简得到65和26。
此时65是奇数而26不是奇数,故把65和26辗转相减:
65-26=39
39-26=13
26-13=13
所以,260与104的最大公约数等于13乘以第一步中约掉的两个2,即1322=52。
1.4.4 代码实现
//定义静态变量,保存约掉的若干个2次数
static int count = 0;
int gcd3(int a, int b)
{
int temp;
//任意给定两个正整数;判断它们是否都是偶数。
if (a % 2 == 0 && b % 2 == 0 && !count)
{
//若是,则用2约简;若不是则执行第二步。
a /= 2;
b /= 2;
//保存约掉的若干个2次数
count += 2;
}
//以较大的数减较小的数,a中保存大数
if (a < b)
{
temp = a;
a = b;
b = temp;
}
//接着把所得的差与较小的数比较,并以大数减小数
if (a - b != 0)
{
//递归求解
return gcd3(b, a - b);
}
else
{
//计算完毕完后count要置为0,防止第二次调用时出错;
//所以需要提前定义常量保存输出结果:约掉的若干个2的积与第二步中等数的乘积就是所求的最大公约数。
int result = count * b;
//置0
count = 0;
return result;
}
}
2. 最小公倍数
2.1 定义
最小公倍数(Least Common Multiple(LCM))是一种数学概念,几个数共有的倍数叫做这几个数的公倍数,其中除0以外最小的一个公倍数,叫做这几个数的最小公倍数。
2.2 解法一:常规法(暴力法)
2.2.1 方法解释
由于最小公倍数的本质是一个最小的能同时被两整数整除的自然数。所以我们先比较两数大小,从较大数开始向上递增,直到找到那个最小公倍数。
2.2.2 代码实现
/** * 常规法求最小公倍数(暴力法) * @param a * @param b * @return */
int lcm1(int a, int b)
{
//首先找到两个数中较大的数,用a存储较大数
if (a < b)
{
int temp = a;
a = b;
b = temp;
}
//从较大数开始寻找符合条件的最小公倍数
for (int i = a;; ++i)
{
if (i % a == 0 && i % b == 0)
{
return i;
}
}
}
2.3 解法二:公式法
2.3.1 定义
由于两个数的乘积等于这两个数的最大公约数与最小公倍数的积。即(a,b)×[a,b]=a×b。所以,求两个数的最小公倍数,就可以先求出它们的最大公约数,然后用上述公式求出它们的最小公倍数。
2.3.2 实例
求[18,20],即得[18,20]=18×20÷(18,20)=18×20÷2=180。求几个自然数的最小公倍数,可以先求出其中两个数的最小公倍数,再求这个最小公倍数与第三个数的最小公倍数,依次求下去,直到最后一个为止。最后所得的那个最小公倍数,就是所求的几个数的最小公倍数。
2.3.3 代码实现
int lcm2(int a, int b)
{
//lcd函数上面已经介绍
return a*b/lcd(a,b);
}
约数,然后用上述公式求出它们的最小公倍数。
2.3.2 实例
求[18,20],即得[18,20]=18×20÷(18,20)=18×20÷2=180。求几个自然数的最小公倍数,可以先求出其中两个数的最小公倍数,再求这个最小公倍数与第三个数的最小公倍数,依次求下去,直到最后一个为止。最后所得的那个最小公倍数,就是所求的几个数的最小公倍数。
2.3.3 代码实现
int lcm2(int a, int b)
{
//lcd函数上面已经介绍
return a*b/lcd(a,b);
}