一个简单的c语言程序实现两个整数求最大公约数

本文分享了一段C语言程序,该程序通过一种较少见的方法实现了求两个整数的最大公约数。程序简单直观,未使用额外的临时变量。

昨天编了一个简单的c语言程序,目的是实现求两个整数的最大公约数,代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int num1 = 0, num2 = 0, gcm = 0;
	int i = 0;
	printf("请输入两个整数:\n");
	scanf("%d %d",&num1,&num2);
	for (i = 0; num1 !=num2; i++)
	{
		if (num1 < num2)
		{
			num1 = num1 + num2;
			num2 = num1 - num2;
			num1 = num1 - num2;
		}
		num1 = num1 - num2;
	}
	gcm = num1;
	printf("这两个整数的最大公约数gcm=%d\n",gcm);
	system("pause");
	return 0;
}

为什么写下来呢,因为我觉得这个程序的运行看起来比较简单,而且不用定义过多的临时变量。而且实现方法也是非常少用的一种求最大公约数的方法,觉得很有趣,所以写下来分享一下。(U_U)
<think>我们要两个整数最大公约数和最小公倍数。最大公约数(Greatest Common Divisor, GCD)是指两个或多个整数共有约数中最大的一个。最小公倍数(Least Common Multiple, LCM)是指两个或多个整数公有的倍数中最小的一个。 根据数学原理,对于两个整数a和b,它们的乘积等于它们的最大公约数和最小公倍数的乘积,即: $$ a \times b = \text{GCD}(a, b) \times \text{LCM}(a, b) $$ 因此,我们可以先最大公约数,然后通过上述关系最小公倍数。 最大公约数常用的方法是欧几里得算法(辗转相除法)。其基本原理是:两个整数最大公约数等于其中较小的数和数相除余数的最大公约数。即: $$ \text{GCD}(a, b) = \text{GCD}(b, a \mod b) $$ 这个过程持续进行,直到余数为0,此时除数就是最大公约数。 最小公倍数则可以通过以下公式计算: $$ \text{LCM}(a, b) = \frac{a \times b}{\text{GCD}(a, b)} $$ 因此,我们可以编写两个函数: 1. gcd(int a, int b) 用于计算最大公约数 2. lcm(int a, int b) 用于计算最小公倍数 注意:在使用公式计算最小公倍数时,要注意a和b的乘积可能会很大,可能会超出int的范围,因此在实际应用中可能需要考虑使用长整型或者先除后乘,但这里我们假设输入在int范围内,且结果不会溢出。 另外,我们还需要考虑输入的是正整数,因此需要确保输入为正整数。如果用户输入非正整数,我们可以要重新输入。 下面是一个完整的C语言程序实现输入两个整数,并输出它们的最大公约数和最小公倍数: ```c #include <stdio.h> // 函数声明 int gcd(int a, int b); int lcm(int a, int b); int main() { int a, b; // 输入两个整数 printf("请输入两个整数:"); scanf("%d %d", &a, &b); // 检查输入是否为正整数 if (a <= 0 || b <= 0) { printf("输入错误:请输入正整数!\n"); return 1; // 非正常退出 } // 计算并输出最大公约数和最小公倍数 printf("最大公约数为:%d\n", gcd(a, b)); printf("最小公倍数为:%d\n", lcm(a, b)); return 0; } // 最大公约数函数,使用欧几里得算法(辗转相除法) int gcd(int a, int b) { // 确保a大于等于b if (a < b) { // 交换a和b int temp = a; a = b; b = temp; } while (b != 0) { int remainder = a % b; a = b; b = remainder; } return a; } // 最小公倍数函数 int lcm(int a, int b) { // 先计算最大公约数 int g = gcd(a, b); // 使用公式:最小公倍数 = 数乘积 / 最大公约数 // 这里先除后乘,避免乘积过大导致溢出 return (a / g) * b; } ``` ### 程序说明: 1. **输入处理**:程序首先要用户输入两个整数,并检查输入是否为正整数。如果输入有误,则提示错误并退出。 2. **gcd函数**:使用辗转相除法计算最大公约数。在计算过程中,通过交换确保a>=b,然后通过循环取余直到余数为0,此时a即为最大公约数。 3. **lcm函数**:利用公式先计算最大公约数,然后通过`(a/gcd)*b`计算最小公倍数。这里先除后乘可以避免大数相乘可能导致的溢出问题(但前提是a和b都能被gcd整除,这是成立的)。 ### 注意事项: - 在计算最小公倍数时,为了避免溢出,我们采用先除后乘的方式。因为`a*b`可能会超出整型范围,而先除以最大公约数(g)可以减小数值。 - 在gcd函数中,我们通过交换保证了a>=b,这样在循环中就可以正常进行辗转相除。但实际上,即使不交换,辗转相除法也能正确工作,因为如果a<b,那么第一次取余操作就会将a和b交换(因为a%b等于a,然后a=b, b=a,相当于交换)。所以我们可以简化gcd函数,去掉交换: ```c int gcd(int a, int b) { while (b != 0) { int temp = a % b; a = b; b = temp; } return a; } ``` 这个版本更简洁,且同样正确。 ### 改进后的gcd函数: 改进后的gcd函数不需要事先判断a和b的大小,因为当a<b时,第一次循环:temp = a % b = a(因为a<b),然后a=b, b=a,相当于交换了a和b,然后继续循环。 因此,我们可以将程序中的gcd函数替换为上述改进版本。 ### 输出示例: ``` 请输入两个整数:12 18 最大公约数为:6 最小公倍数为:36 ``` ``` 请输入两个整数:7 13 最大公约数为:1 最小公倍数为:91 ``` ### 相关问题: 1. 如何多个正整数最大公约数和最小公倍数? 2. 欧几里得算法(辗转相除法)的时间复杂度是多少? 3. 除了辗转相除法,还有哪些方法可以最大公约数? 4. 如何避免在计算最小公倍数时发生整数溢出? </think>### C语言实现两个整数最大公约数和最小公倍数 以下是使用C语言实现两个整数最大公约数(GCD)和最小公倍数(LCM)的高效方法: ```c #include <stdio.h> // 函数声明 int gcd(int a, int b); int lcm(int a, int b); int main() { int num1, num2; // 输入两个整数 printf("请输入两个整数(空格分隔):"); scanf("%d %d", &num1, &num2); // 验证输入有效性 if (num1 <= 0 || num2 <= 0) { printf("错误:请输入正整数!\n"); return 1; } // 计算并输出结果 printf("最大公约数(GCD):%d\n", gcd(num1, num2)); printf("最小公倍数(LCM):%d\n", lcm(num1, num2)); return 0; } // 使用欧几里得算法计算最大公约数 int gcd(int a, int b) { while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } // 计算最小公倍数(基于GCD) int lcm(int a, int b) { return (a / gcd(a, b)) * b; } ``` ### 关键点说明: 1. **欧几里得算法(辗转相除法)**: - 基于数学原理:$ \text{GCD}(a, b) = \text{GCD}(b, a \mod b) $ - 时间复杂度:$ O(\log(\min(a,b))) $,高效可靠[^2] 2. **最小公倍数计算**: - 利用数学关系:$ \text{LCM}(a, b) = \frac{|a \times b|}{\text{GCD}(a, b)} $ - 实现优化:`(a / gcd(a, b)) * b` 避免大数相乘溢出[^5] 3. **输入验证**: - 检查输入是否为正整数 - 处理无效输入(如负数或零) ### 示例运行: ``` 请输入两个整数(空格分隔):24 36 最大公约数(GCD):12 最小公倍数(LCM):72 ``` ``` 请输入两个整数(空格分隔):17 31 最大公约数(GCD):1 最小公倍数(LCM):527 ``` ### 算法优势: 1. **时间复杂度**: - GCD计算:$ O(\log n) $ - LCM计算:$ O(\log n) $(复用GCD结果) 远优于$ O(n) $的暴力枚举方法[^3] 2. **正确性**: - 满足数学关系:$ a \times b = \text{GCD}(a, b) \times \text{LCM}(a, b) $ - 处理边界情况(如互质数、倍数关系等)[^4] 3. **资源效率**: - 空间复杂度:$ O(1) $ - 无递归调用避免栈溢出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值