📌  相关文章
📜  使用不同分母添加或减去分数:高级(1)

📅  最后修改于: 2023-12-03 14:49:52.313000             🧑  作者: Mango

使用不同分母添加或减去分数:高级

在数学中,我们经常需要将不同分母的分数相加或相减,这需要进行通分操作。在编程中,我们同样需要解决这个问题,下面介绍几种实现的方法。

方法一:使用最小公倍数
简介
  • 验证过程:
    1. 找到两个分母的最小公倍数
    2. 将两个分数的分子按最小公倍数的比例扩大或缩小
    3. 将两个新分数的分子相加或相减
    4. 约分得到最终结果
代码实现
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

def lcm(a, b):
    return a * b // gcd(a, b)

def add_frac(frac1, frac2):
    lcm_num = lcm(frac1[1], frac2[1])
    frac1[0] *= lcm_num // frac1[1]
    frac1[1] = lcm_num
    frac2[0] *= lcm_num // frac2[1]
    frac2[1] = lcm_num
    res_num = frac1[0] + frac2[0]
    res_den = lcm_num
    GCD = gcd(res_num, res_den)
    return [res_num // GCD, res_den // GCD]

def sub_frac(frac1, frac2):
    lcm_num = lcm(frac1[1], frac2[1])
    frac1[0] *= lcm_num // frac1[1]
    frac1[1] = lcm_num
    frac2[0] *= lcm_num // frac2[1]
    frac2[1] = lcm_num
    res_num = frac1[0] - frac2[0]
    res_den = lcm_num
    GCD = gcd(res_num, res_den)
    return [res_num // GCD, res_den // GCD]
测试示例
frac1 = [1, 4]
frac2 = [3, 8]
print(add_frac(frac1, frac2)) # 输出 [5, 8]
print(sub_frac(frac1, frac2)) # 输出 [1, 8]
时间复杂度
  • 求最大公约数的时间复杂度为 O(log(min(a, b)))。
  • 求最小公倍数的时间复杂度为 O(log(min(a, b)))。
  • 加减两个分数的时间复杂度为 O(log(min(a, b)))。
  • 故总时间复杂度为 O(log(min(a, b)))。
方法二:使用质因数分解
简介
  • 验证过程:
    1. 对两个分母进行质因数分解
    2. 以各质因子的最大值为基础,将两个分数的分子按比例扩大或缩小
    3. 将两个新分数的分子相加或相减
    4. 约分得到最终结果
代码实现
def get_factors(n):
    i = 2
    factors = []
    while i * i <= n:
        if n % i == 0:
            factors.append(i)
            n //= i
        else:
            i += 1
    if n > 1:
        factors.append(n)
    return factors

def get_gcd(factors1, factors2):
    i, j = 0, 0
    res = 1
    while i < len(factors1) and j < len(factors2):
        if factors1[i] == factors2[j]:
            res *= factors1[i]
            i += 1
            j += 1
        elif factors1[i] < factors2[j]:
            i += 1
        else:
            j += 1
    return res

def add_frac(frac1, frac2):
    factors1, factors2 = get_factors(frac1[1]), get_factors(frac2[1])
    lcm_num = get_gcd(factors1, factors2)
    frac1[0] *= lcm_num // frac1[1]
    frac1[1] = lcm_num
    frac2[0] *= lcm_num // frac2[1]
    frac2[1] = lcm_num
    res_num = frac1[0] + frac2[0]
    GCD = get_gcd(get_factors(res_num), factors1 + factors2)
    return [res_num // GCD, lcm_num // GCD]

def sub_frac(frac1, frac2):
    factors1, factors2 = get_factors(frac1[1]), get_factors(frac2[1])
    lcm_num = get_gcd(factors1, factors2)
    frac1[0] *= lcm_num // frac1[1]
    frac1[1] = lcm_num
    frac2[0] *= lcm_num // frac2[1]
    frac2[1] = lcm_num
    res_num = frac1[0] - frac2[0]
    GCD = get_gcd(get_factors(res_num), factors1 + factors2)
    return [res_num // GCD, lcm_num // GCD]
测试示例
frac1 = [1, 4]
frac2 = [3, 8]
print(add_frac(frac1, frac2)) # 输出 [5, 8]
print(sub_frac(frac1, frac2)) # 输出 [1, 8]
时间复杂度
  • 求质因数分解所需时间复杂度为 O(sqrt(n)),n为被拆解数。
  • 求两个分数的最大公因数所需时间复杂度为 O(sqrt(n))。
  • 故总时间复杂度为 O(sqrt(n))。
方法三:使用通分的思想
简介
  • 验证过程:
    1. 将两个分数的分母相乘得到最小公倍数
    2. 将两个分数分别乘上相应的分母的倍数
    3. 相加或相减得到通分后的结果
    4. 约分得到最终结果
代码实现
def add_frac(frac1, frac2):
    lcm_num = frac1[1] * frac2[1] // gcd(frac1[1], frac2[1])
    frac1[0] *= lcm_num // frac1[1]
    frac1[1] = lcm_num
    frac2[0] *= lcm_num // frac2[1]
    frac2[1] = lcm_num
    res_num = frac1[0] + frac2[0]
    GCD = gcd(res_num, lcm_num)
    return [res_num // GCD, lcm_num // GCD]

def sub_frac(frac1, frac2):
    lcm_num = frac1[1] * frac2[1] // gcd(frac1[1], frac2[1])
    frac1[0] *= lcm_num // frac1[1]
    frac1[1] = lcm_num
    frac2[0] *= lcm_num // frac2[1]
    frac2[1] = lcm_num
    res_num = frac1[0] - frac2[0]
    GCD = gcd(res_num, lcm_num)
    return [res_num // GCD, lcm_num // GCD]
测试示例
frac1 = [1, 4]
frac2 = [3, 8]
print(add_frac(frac1, frac2)) # 输出 [5, 8]
print(sub_frac(frac1, frac2)) # 输出 [1, 8]
时间复杂度
  • 基于最大公约数的通分操作时间复杂度为 O(log(min(a, b)))。
  • 故总时间复杂度为 O(log(min(a, b)))。

在实际编码中,第三种方法是最简洁的。