文章目录
求最大公约数
今天看了翁凯老师的b站上c语言的第46集(5.3.3)后对其中的一些方法感觉很妙,故进行些许分析和探讨
一、问题
输入两个数a和b,输出它们的最大公约数
输入12 18
输出6
二、解题方法
1.暴力搜索法(brute force method)
先看翁凯老师的第一种方法:
#include <stdio.h>
int main()
{
int a,b;
int min;
scanf("%d %d",&a,&b);
if (a<b){
min=a;
}else {
min=b;
}
int i;
int ret;
for(i=1;i<min;i++){
if(a%i==0){
if(b%i==0){
ret=i;
}
}
}
printf("a 和 b 的最大公约数是%d",ret);
return 0;
}
首先我们检查一下代码有没有错误
其实是有个小错误(在频弹幕中也有提示,不过大家当时可能没注意)。其实这里i<min应该改为i<=min
我们看看原代码的运行结果:
显然运行结果不是我们想要的
那么为什么i要<=min呢?
这是因为最大公约数(GCD)可能是两个数中较小的那个数本身。例如,如果 a 是 6,b 是 12,那么它们的最大公约数是 6。
所以正确修改后的代码应该为:
#include <stdio.h>
int main()
{
int a,b;
int min;
scanf("%d %d",&a,&b);
if (a<b){
min=a;
}else {
min=b;
}
int i;
int ret = 1; // 初始化最大公约数为 1
for(i=1;i<=min;i++){ // 循环条件修改为 i <= min
if(a%i==0){
if(b%i==0){
if(i > ret){ // 如果当前的公约数 i 大于之前保存的最大公约数 ret ,则更新 ret
ret = i;
}
}
}
}
printf("a 和 b 的最大公约数是 %d\n",ret);
return 0;
}
我们让gpt对该方法做下点评:
2欧几里得算法(Euclidean Algorithm)
先看翁凯老师的提示:
看看我根据提示写出来的代码:
#include <stdio.h>
int main() {
int a, b;
int t;
scanf("%d %d", &a, &b);
int m = a;
int n = b;
// 使用欧几里得算法计算 GCD
for (; b != 0; ) {
t = a % b;
a = b;
b = t;
}
printf("%d和%d的最大公约数是%d", m, n, a);
return 0;
}
翁凯老师和我的差不多,不过他将for换成了while更加简洁
看看代码逻辑:
初始化与输入:
读取两个整数 a
和 b
。
用 m
和 n
保存原始输入值,以便在最后输出时使用。
欧几里得算法:
该算法通过连续取模的方式不断缩小两个数的范围,最终得到它们的最大公约数。
循环条件为 b != 0
,即当 b
为零时,a
就是最大公约数。
具体步骤如下:
- Step 1: 计算
t = a % b
,即a
除以b
的余数。 - Step 2: 将
a
更新为b
。 - Step 3: 将
b
更新为t
。 - Step 4: 重复步骤 1 到 3,直到
b
等于零。
当 b
为零时,a
即为两个数的最大公约数。
输出结果:
使用格式化字符串输出两个原始输入值和计算得到的最大公约数。
算法逻辑
这里我将询问chatGPT并引用回答(有错误之处还请谅解和指正)
欧几里得算法原理
数学定理
欧几里得算法的核心基于以下数学定理:
定理: 如果 a
和 b
是两个整数且 a > b
,那么 GCD(a, b) = GCD(b, a % b)
。
GCD(a, b)
表示a
和b
的最大公约数。a % b
是a
除以b
的余数。
原理解释
最大公约数的特性
- 假设
d
是a
和b
的公约数,那么它也一定是b
和a % b
的公约数。 - 这是因为,如果
a
可以表示为a = k * b + r
(其中k
是整数,r
是余数,即r = a % b
),则任何能同时整除a
和b
的数,也必然能整除r
。 - 例如,若
a = 56
和b = 12
,则a = 4 * 12 + 8
,因此56 % 12 = 8
。
不断缩小问题规模
- 通过反复使用这个性质,可以将问题规模不断缩小,即用较小的余数取代较大的数,直到余数为 0。
- 当余数为 0 时,剩下的非零数即为
a
和b
的最大公约数。
终止条件
- 当余数为 0 时,说明较大的数已经被较小数的倍数整除,最后的非零数就是最大公约数。
算法步骤
初始化
- 设定两个整数
a
和b
。
重复以下步骤直到 b = 0
- 计算
t = a % b
。 - 更新
a
为b
。 - 更新
b
为t
。
返回结果
- 当
b = 0
时,当前a
的值即为最大公约数。
示例
假设我们要计算 56
和 12
的最大公约数:
- 初始:
a = 56
,b = 12
。 - 第一步:计算
t = 56 % 12 = 8
,更新a = 12
,b = 8
。 - 第二步:计算
t = 12 % 8 = 4
,更新a = 8
,b = 4
。 - 第三步:计算
t = 8 % 4 = 0
,更新a = 4
,b = 0
。 - 结束:当
b = 0
时,最大公约数为a = 4
。
为什么欧几里得算法有效
- 效率高: 每一步都会显著缩小较大的数,算法的迭代次数与数字大小的对数成正比,复杂度为
O(log(min(a, b)))
。 - 实现简单: 算法只需基本的除法和取余操作,不需要复杂的数据结构。
总结
这就是今天的问题分享,写作过程中借用了chatGPT,不得不说真的强和好用。不过还是会有bug
在网上看到的,自己试了一下,还真是 😂
每日一句
“生活不可能像你想象得那么美好,但也不会像你想象得那么糟糕。” – 赫尔曼·黑塞
感谢观看