求两个小数的“最小公倍数”

35 篇文章 27 订阅

Part.I 函数实现

def get_lcm(a, b):
    for i in range(min(a,b),0,-1):
        if a % i ==0 and b % i == 0:
            return a*b//i

def get_digNum(dig):
    s = str(dig)
    info = s.split('.')
    if len(info)<2:
        return 0
    return len(info[1])

def get_diglcm(a, b):
    times = 10 ** max(get_digNum(a),get_digNum(b))
    lcm = get_lcm(round(a * times), round(b * times)) #不用int是为了防止小数取位误差
    return lcm/times

上面三个小函数的意义如下:

  • get_lcm:求取两个整数的最小公倍数
  • get_digNum:得到一个小数的“实际”小数位数
  • get_diglcm:求取两个小数的最小公倍数

调用示例:

num1 = 1575.42
num2 = 1227.60
print(get_diglcm(num1, num2))
input()

输出为94525.2

Chap.I 轮子备份

下面是用『辗转相除法』求最大公约数(greatest common divisor) g c d gcd gcd,然后根据最小公倍数(least common multiple) l c m = a × b g c d lcm=\frac{a\times b}{gcd} lcm=gcda×b来求最小公倍数 l c m lcm lcm 的。

def lcm(a: int, b: int) -> int:
    a1=a;b1=b
    while(b!=0):
        tmp=a%b
        a=b
        b=tmp
    return a1*b1/a

Part.II 心路历程

最小公倍数:公倍数(common multiple)是指在两个或两个以上的自然数中,如果它们有相同的倍数,这些倍数就是它们的公倍数。公倍数中最小的,就称为这些整数的最小公倍数(lowest common multiple)。

题目是【求两个“小数”的最小公倍数】,是的,你没看错,就是求两个小数的“最小公倍数”。笔者这里的意思是,比如我有两个小数A、B,我想找两个整数a、b,使得a*A=b*B

首先回顾一下最小公倍数的求法:

  • 列举倍数法:分别列举出要求最小公倍数的那几个数的一些倍数,从中找出除“0”以外最小的那个公倍数,就是最小公倍数。
  • 分解质因数法:就是先把要求最小公倍数的那几个数分别分解质因数,然后将原来几个数里所含该质因数的最多个数的每一个质因数相乘,所得的积就是要求的最小公倍数。
  • 短除法:用短除法求两个数的最小公倍数,一般都用这两个数除以它们的公因数,一直除到所得的两个商只有公因数1为止。把所有的除数和最后的两个商连乘起来,就得到这两个数的最小公倍数。
  • 公式法:所谓公式法(最大公约数与最小公倍数关系)就是对于任意两个自然数a、b,只要先求出这两个数的最大公约数后,利用公式[a,b] ×(a,b)=a×b即可求出最小公倍数[a,b]=a×b÷(a,b),也即是两个数的最小公倍数等于这两个数的乘积除以这两个数的最大公约数。
  • 辗转相减后相乘法:求两个数的最小公倍数,如两个数相差2倍以内,就可用辗转相减后相乘法,即连续用大数去减小数,直到所得的差能同时整除原来两个数为止,然后用这个差与整除的两个商相乘,所得的乘积就是两个数的最小公倍数。
  • 大数翻倍法:所谓大数翻倍法就是要求两个数的最小公倍数,可以将大数从两倍找起,直到找出的数是小数的倍数(即出现新的倍数关系为止),这个倍数就是这两个数的最小公倍数。
  • 小数缩倍后相乘法:小数缩倍后相乘法就是求两个数的最小公倍数。如果这两个数不成倍数关系,就把小数依次除以2,3,4,5……直到除得的商能整除较大数为止,然后用这个商除以较大数所得的商与原来小数相乘所得的积就是这两个数的最小公倍数。
  • 肉眼判断法:想拥有

在网上找到了现成的小函数:

https://blog.csdn.net/byakki/article/details/86607831

def lcm(a, b):
    for i in range(min(a,b),0,-1):
        if a % i ==0 and b % i == 0:
            return a*b//i

它的实现思想是公式法。

如果把小数都乘 1 0 n 10^n 10n,乘后的数就变成了整数,之后再求两个整数的最小公倍数,这个公倍数再除以 1 0 n 10^n 10n 得到的数是否是我所需要的“最小公倍数”?

还有另一种提法:两个数放大n倍后的最小公倍数是否是这两个数最小公倍数的n倍?

好像是吧,具体证明先不管了,上面思路的代码如下:

def get_lcm(a, b):
    for i in range(min(a,b),0,-1):
        if a % i ==0 and b % i == 0:
            return a*b//i

def get_digNum(dig):
    s = str(dig)
    info = s.split('.')
    if len(info)<2:
        return 0
    return len(info[1])

def get_diglcm(a, b):
    times = 10 ** max(get_digNum(a),get_digNum(b))
    lcm = get_lcm(round(a * times), round(b * times)) #不用int是为了防止小数取位误差
    return lcm/times

上面三个小函数的意义如下:

  • get_lcm:求取两个整数的最小公倍数
  • get_digNum:得到一个小数的“实际”小数位数
  • get_diglcm:求取两个小数的最小公倍数

调用示例:

num1 = 1575.42
num2 = 1227.60
print(get_diglcm(num1, num2))
print(round(get_diglcm(num1, num2)/num1))
print(round(get_diglcm(num1, num2)/num2))
input()

输出为

94525.2
60
77
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪猪头拯救地球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值