辗转相除法
欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。应用领域有数学和计算机两个方面。————百度百科
本文不对该算法进行证明,只阐述一下该算法的计算过程和代码实现
- 问题一:求1997和615两个整数的最大公约数
- 1997 / 615 = 3(余152)
- 615 / 152 = 4(余7)
- 152 / 7 = 21(余5)
- 7 / 5 = 1 (余2)
- 5 / 2 = 2 (余1)
- 2 / 1 = 2 (余0)
此时1为两个整数的最大公约数
- 问题二:求3139和2117两个整数的最大公约数
- 3139 / 2117 = 1(余1022)
- 2177 / 1022 = 2 (余73)
- 1022 / 73 = 14(余0)
此时73为两个整数的最大公约数
- 什么时候停止计算——>循环条件
- 当一个数除另一个数,余数为0,余数为0的表达式中,73即需要求得的最大公约数
- 1022 / 73 = 14(余0),余数为0的除数73为所求值
- 下一次循环计算的值如何改变——>迭代表达式
- 上一次循环的除数作为下一次循环的被除数,上一次循环的余数作为下一次循环的除数
- (不会有人不知道被除数,除数是在前还是在后吧)
- 被除数的前一个,除数是后一个
明白了上面两个问题之后,接下来要做的就是代码实现了
#include <stdio.h>
int main() {
int a = 1997, b = 615;
// 循环条件:当一个数除另一个数,余数为0的时候循环结束,故如果a % b !=0则一直循环
// 答案:余数为0的表达式中,除数为最大公约数
while (a % b != 0) {
// 迭代表达式
// 该次循环的除数也就是b作为下一次计算的被除数即把b的值赋给a,这一步都能理解a = b;
int c = a;
a = b;
/* 该次循环的余数作为下一次计算的除数也就是----->b = (a % b),看起来好像是这样写没错,但是忽略了一个问题,a在上面一个
表达式中已经被改变了原先的值*/
// 故我们需要对原始的变量a的值用另一个变量c进行存储故int c = a;但这个表达式不能写在下方,得写在a = b;的上方,得在a变化前对它进行记录
// 就从b = (a % b)--------->b = (c % b);
b = (c % b);
}
printf("%d",b);
return 0;
}
// 运行步骤
/*
1997 / 615 = 3(余152)
615 / 152 = 4(余7)
152 / 7 = 21(余5)
7 / 5 = 1(余2)
5 / 2 = 2(余1)
2 / 1 = 2(余0)
*/
// 如果想要看到运行步骤可以把while后后面的输出改一下
#include <stdio.h>
int main() {
int a = 1997, b = 615;
// 循环条件:当一个数除另一个数,余数为0的时候循环结束,故如果a % b !=0则一直循环
// 答案:余数为0的表达式中,除数为最大公约数
while (a % b != 0) {
printf("%d / %d = %d(余%d)\n",a,b,a/b,a%b);
// 迭代表达式
// 该次循环的除数也就是b作为下一次计算的被除数即把b的值赋给a,这一步都能理解a = b;
int c = a;
a = b;
/* 该次循环的余数作为下一次计算的除数也就是----->b = (a % b),看起来好像是这样写没错,但是忽略了一个问题,a在上面一个
表达式中已经被改变了原先的值*/
// 故我们需要对原始的变量a的值用另一个变量c进行存储故int c = a;但这个表达式不能写在下方,得写在a = b;的上方,得在a变化前对它进行记录
// 就从b = (a % b)--------->b = (c % b);
b = (c % b);
}
printf("%d / %d = %d(余%d)\n",a,b,a/b,a%b);
return 0;
}
代码如何实现的,具体思考步骤和写法都已经在注释中阐明
如果有问题,可以私信或者评论区提问