你好呀~

最大公约数与最小公倍数的最快速求法

一. 前言

  我们不需要记住那么多知识,我们需要的是会合理的调用知识。

  不要当个硬盘,要当cpu。

  如求最大公约数/最小公倍数方法各种各样,数不胜数,难道我们全部都要记住吗?

  不需要,记住最优解就行啦,这里直接告诉大家答案:最大公约数用math.gcd函数;最小公倍数用两数之积除以最小公倍数。

 

二. 求解方法

import math


# 最大公约数-------------------------------------------------------------------------
def max_divisor1(a, b):
    """
    暴力枚举法:遍历小的数的一半值,如果能都将它们整除,那么就是该值。
    """
    big = max(a, b)
    small = min(a, b)
    if big % small == 0:
        return small
    for i in range(small // 2, 1, -1):
        if small % i == 0 and big % i == 0:
            return i
    return 1


def max_divisor2(a, b):
    """
    辗转相除法(欧几里得算法、递归算法):两个数本身相除,取余值和最小值再相除,直到整除
    """
    big = max(a, b)
    small = min(a, b)
    if big % small == 0:
        return small
    return max_divisor2(big % small, small)


def max_divisor3(a, b):
    """
    更相减损法:两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b之间的最大公约数。(即:每次都是求差值和较小数之间最大公约数,直到两个数相等为止,最大公约数就是最终相等的这两个数的值。避免了取模运算,但是算法性能不稳定,最坏时间复杂度为O(max(a,b))。缺点:更相减损术是不稳定的算法,当两数相差悬殊时,如计算10000和1的最大公约数,就要递归9999次。运算次数太多,
    """
    if a == b:
        return a
    big = max(a, b)
    small = min(a, b)
    return max_divisor3(big - small, small)


def max_divisor4(a, b):
    """
    把辗转相除法和更相减损术结合起来,在更相减损术的基础上使用移位运算。(移位运算差不多是辗转相除法的运用,不过是遇到偶数时,每次向右移一位,对于整数十进制来说,相当于除以2)求最大公约数的方法简写为gcd.
    当a、b均为偶数时,dvr(a,b)=2gcd(a/2,b/2)=2dvr(a>>1,b>>1)=dvr(a>>1,b>>1)<<1
    当a为偶数b为奇数时,dvr(a,b)=dvr(a/2,b)=dvr(a>>1,b)
    当a为奇数b为偶数时,dvr(a,b)=dvr(a,b/2)=dvr(a,b>>1)
    当a、b均为奇数时,先利用更相减损术减一次,dvr(a,b)=dvr(a-b,b),此时a-b必为偶数,然后又可以继续进行移位运算。
    移位运算的性能非常好。这种方法在两数都比较小时,看不出来计算的优势;当两数越大时,计算次数的减少就会越明显。这种方法既避免大整数取模,又减少了运算次数,而且算法性能稳定,时间复杂度为O(log(max(a,b)))

    补充:
    &    与    两个位都为1时,结果才为1
    |    或    两个位都为0时,结果才为0
    ^    异或    两个位相同为0,相异为1
    ~    取反    0变1,1变0
    <<    左移    各二进位全部左移若干位,高位丢弃,低位补0
    >>    右移    各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
    """
    if a == b:
        return a
    if (a & 1) == 0 and (b & 1) == 0:
        return max_divisor4(a >> 1, b >> 1) << 1
    elif (a & 1) == 0 and (b & 1) != 0:
        return max_divisor4(a >> 1, b)
    elif (a & 1) != 0 and (b & 1) == 0:
        return max_divisor4(a, b >> 1)
    else:
        big = max(a, b)
        small = min(a, b)
        return max_divisor4(big - small, small)


# 最小公倍数------------------------------------------------------------------------------
def min_multiple1(x, y):
    """
    找到最大值进行递增直到全部整除
    """
    greater = x if x > y else y
    while True:
        if (greater % x == 0) and (greater % y == 0):
            lcm = greater
            break
        greater += 1

    return lcm


# 最简操作
def max_divisor_min_multiple(x, y):
    """
    最大公约数:gcd方法
    最小公倍数:两数之积整除最大公约数,math模块没必要再搞个方法
    """
    # return math.gcd(x, y)
    return (x * y) // math.gcd(x, y)


if __name__ == '__main__':
    print(max_divisor_min_multiple(4, 8))

 

posted @ 2021-03-04 17:48  测神  阅读(686)  评论(0编辑  收藏  举报