辗转相除法求最大公约数


求最大公约数

今天看了翁凯老师的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对该方法做下点评:

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更加简洁

看看代码逻辑:

初始化与输入:

读取两个整数 ab

mn 保存原始输入值,以便在最后输出时使用。

欧几里得算法:

该算法通过连续取模的方式不断缩小两个数的范围,最终得到它们的最大公约数。

循环条件为 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并引用回答(有错误之处还请谅解和指正)

欧几里得算法原理
数学定理

欧几里得算法的核心基于以下数学定理:

定理: 如果 ab 是两个整数且 a > b,那么 GCD(a, b) = GCD(b, a % b)

  • GCD(a, b) 表示 ab 的最大公约数。
  • a % ba 除以 b 的余数。
原理解释
最大公约数的特性
  • 假设 dab 的公约数,那么它也一定是 ba % b 的公约数。
  • 这是因为,如果 a 可以表示为 a = k * b + r (其中 k 是整数,r 是余数,即 r = a % b),则任何能同时整除 ab 的数,也必然能整除 r
  • 例如,若 a = 56b = 12,则 a = 4 * 12 + 8,因此 56 % 12 = 8
不断缩小问题规模
  • 通过反复使用这个性质,可以将问题规模不断缩小,即用较小的余数取代较大的数,直到余数为 0。
  • 当余数为 0 时,剩下的非零数即为 ab 的最大公约数。
终止条件
  • 当余数为 0 时,说明较大的数已经被较小数的倍数整除,最后的非零数就是最大公约数。
算法步骤
初始化
  • 设定两个整数 ab
重复以下步骤直到 b = 0
  1. 计算 t = a % b
  2. 更新 ab
  3. 更新 bt
返回结果
  • b = 0 时,当前 a 的值即为最大公约数。
示例

假设我们要计算 5612 的最大公约数:

  • 初始:a = 56b = 12
  • 第一步:计算 t = 56 % 12 = 8,更新 a = 12b = 8
  • 第二步:计算 t = 12 % 8 = 4,更新 a = 8b = 4
  • 第三步:计算 t = 8 % 4 = 0,更新 a = 4b = 0
  • 结束:当 b = 0 时,最大公约数为 a = 4
为什么欧几里得算法有效
  • 效率高: 每一步都会显著缩小较大的数,算法的迭代次数与数字大小的对数成正比,复杂度为 O(log(min(a, b)))
  • 实现简单: 算法只需基本的除法和取余操作,不需要复杂的数据结构。

总结

这就是今天的问题分享,写作过程中借用了chatGPT,不得不说真的强和好用。不过还是会有bug

在这里插入图片描述
在网上看到的,自己试了一下,还真是 😂

每日一句

“生活不可能像你想象得那么美好,但也不会像你想象得那么糟糕。” – 赫尔曼·黑塞

感谢观看

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值