问题描述:
给定两个正整数,求它们的最大公约数和最小公倍数。
提高要求:
三个以上数的求解。
解题思路:
对于这个问题,求最大 公约数的算法有很多,例如:穷举法,即传进来两个数,选择最小的那个数,作为 最开始的最大公约数,向下穷举,知道都可以被整除为止,但是这种算法太笨拙。还有欧几里得算法,辗转相除。我采用的算法公式:gcd(a, b) = gcd(b, a%b),前提条件是a>b,即保证大数在前。最小公平倍数的公式为:a*b/gcd(a,b)。有了这个公式就可以进行计算求解,对于三个以上的数求解,利用穷举法可以求得,但是效率慢了很多, 但是在条件控制上优化一下,还是可以的。我这次试用python编写,原因大家一看便知:
求解最大公约数的代码:
def gcd(x, y):
"""
欧几里得算法求解两个数的最大公约数
:param x: 第一个数
:param y: 第二个数
:return: 最大公约数
"""
# 保证大数在前
if y > x:
x, y = y, x
if y == 0:
return x
# 递归递归调用,公式为: gcd(a, b) = gcd(b, a % b){a > b}
return gcd(y, x % y)
非常简洁的代码,交换两个值再也不用第三个变量了。
求解最小公平倍数的代码:
def lcm(x, y):
"""
计算两个数的最小公倍数
:param x: 第一个数
:param y: 第二个数
:return: 最小公倍数
"""
# 公式: a, b两个数的最小公倍数等于a*b除以a,b的最大公约数
return int(x*y/gcd(x, y))
三个以上的数的求解函数:
def gcd_lcm(*x):
"""
穷举法计算最小公倍数与最大公约数
:param x: 不定长参数
:return:
"""
num = []
flag, gcd_, lcm_ = 1, 1, 1
for i in x:
num.append(i)
# 计算这一组数中的乘积,即最大公倍数
lcm_ *= i
# 计算这组数中的最大最小值
max_, min_ = max(num), min(num)
# 穷举计算最大公约数:
while min_ > 0:
for x in num:
if x % min_ == 0:
flag = 1
# 当前值与待定的公因数的余数不等于0
else:
# 判断的标志设为0,并且不继续往下验证其他的数,进行下一个公因数验证
flag = 0
break
if flag == 1:
gcd_ = min_
break
min_ -= 1
# 穷举计算最小公倍数, 原理类似最大公因数的求解
while max_ <= lcm_:
for y in num:
if max_ % y == 0:
flag = 1
else:
flag = 0
break
if flag == 1:
lcm_ = max_
break
max_ += 1
return gcd_, lcm_
运行与调试结果:
断点调试查看变量的值的变化:
三个以上的数的计算结果:
输入:3,15,18
结果为:最大公因数,最小公倍数 = 3, 90