优化分数计算器代码的建议(提高速度和减少内存使用)

5 投票
6 回答
3453 浏览
提问于 2025-04-15 23:38

基本上,我需要这个程序能做的就是充当一个简单的分数计算器(可以进行加法、减法、乘法和除法),处理一行输入,比如说:
- 输入:1/7 + 3/5
- 输出:26/35

我最开始的代码是:

import sys

def euclid(numA, numB):
    while numB != 0:
        numRem = numA % numB
        numA = numB
        numB = numRem
    return numA

for wejscie in sys.stdin:
    wyjscie = wejscie.split(' ')
    a, b = [int(x) for x in wyjscie[0].split("/")]
    c, d = [int(x) for x in wyjscie[2].split("/")]
    if wyjscie[1] == '+':
        licz = a * d + b * c
        mian= b * d
        nwd = euclid(licz, mian)
        konA = licz/nwd
        konB = mian/nwd
        wynik = str(konA) + '/' + str(konB)
        print(wynik)
    elif wyjscie[1] == '-':
        licz= a * d - b * c
        mian= b * d
        nwd = euclid(licz, mian)
        konA = licz/nwd
        konB = mian/nwd
        wynik = str(konA) + '/' + str(konB)
        print(wynik)
    elif wyjscie[1] == '*':
        licz= a * c
        mian= b * d
        nwd = euclid(licz, mian)
        konA = licz/nwd
        konB = mian/nwd
        wynik = str(konA) + '/' + str(konB)
        print(wynik)
    else:
        licz= a * d
        mian= b * c
        nwd = euclid(licz, mian)
        konA = licz/nwd
        konB = mian/nwd
        wynik = str(konA) + '/' + str(konB)
        print(wynik)

然后我把它简化成了:

import sys

def euclid(numA, numB):
    while numB != 0:
        numRem = numA % numB
        numA = numB
        numB = numRem
    return numA

for wejscie in sys.stdin:
    wyjscie = wejscie.split(' ')
    a, b = [int(x) for x in wyjscie[0].split("/")]
    c, d = [int(x) for x in wyjscie[2].split("/")]
    if wyjscie[1] == '+':
        print("/".join([str((a * d + b * c)/euclid(a * d + b * c, b * d)),str((b * d)/euclid(a * d + b * c, b * d))]))
    elif wyjscie[1] == '-':
        print("/".join([str((a * d - b * c)/euclid(a * d - b * c, b * d)),str((b * d)/euclid(a * d - b * c, b * d))]))
    elif wyjscie[1] == '*':
        print("/".join([str((a * c)/euclid(a * c, b * d)),str((b * d)/euclid(a * c, b * d))]))
    else:
        print("/".join([str((a * d)/euclid(a * d, b * c)),str((b * c)/euclid(a * d, b * c))]))

如果有任何建议可以让我进一步改进这个代码,我非常欢迎。

补充一下,我忘了提 - 这个代码不能使用除了sys以外的任何库。

6 个回答

1

你可以在 euclid 函数中使用 记忆化,这可能会根据输入的数据加快速度。不过,这样会占用更多的内存。

你还可以在 euclid 中使用元组赋值。

def euclid(numA, numB):
    while numB != 0:
        numA, numB = numB, numA % numB
    return numA

在这里使用 map 会更快。

a, b, c, d = map(int, wyjscie[0].split("/")+wyjscie[2].split("/"))
9

你可以做的最大改进就是使用Python(2.6)中的fractions库:

>>> import fractions
>>> fractions.Fraction(1,7) + fractions.Fraction("3/5")
Fraction(26, 35)
5

我会创建一个类,这个类里面有两个字段,分别是 numerator(分子)和 denominator(分母),这两个字段都是整数。同时,这个类还会实现一些方法,比如 __add__(加法)、__sub__(减法)、__mul__(乘法)和 __div__(除法)。这样一来,你就可以用普通的数学运算来处理这些实例了。

虽然这样做可能对你的需求来说有点过于复杂,但代码会显得更整洁。

实际上,这种基于类的方法正是 fractions 模块的实现方式。通常我会建议你看看 fractions 模块的源代码,了解它是怎么写的,但因为这是作业,我不确定这样做是否合适。等作业完成后,可以看看这个模块,了解一下完整的分数类型是怎么实现的。

撰写回答