Подсказки для того, чтобы заставить дробный калькулятор кодировать более оптимизированный (быстрее и использовать меньше памяти)

Basicly, в чем я нуждаюсь, чтобы программа сделала, должен действовать как калькулятор простой дроби (для дополнения, вычитания, умножения и разделения) для одна строка входа, например:
- вход: 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.

5
задан Bill the Lizard 20 September 2012 в 12:48
поделиться

5 ответов

Я бы создал класс, содержащий поля numerator и denominator (оба целые числа) и реализующий методы __add__, __sub__, __mul__ и __div__. Затем вы можете просто использовать обычные математические функции для объединения экземпляров.

Это может быть излишеством для ваших целей, но код будет намного чище.

На самом деле, подход на основе классов - это именно то, как реализован модуль дробей. Обычно я бы предложил изучить исходный код модуля дробей, чтобы посмотреть, как он написан, но поскольку это домашнее задание, я не уверен, что это разрешено. Возможно, стоит посмотреть после выполнения задания, чтобы увидеть, как реализован полноценный тип дробных чисел.

5
ответ дан 18 December 2019 в 09:47
поделиться

Вы можете убрать код, который сводит дробь к наименьшим членам из отдельных '+', '-' и т.д. Это сделает код немного чище, компактнее и читабельнее.

1
ответ дан 18 December 2019 в 09:47
поделиться

Вычленение на множители евклида во вспомогательную функцию - хорошая идея. Я бы посоветовал попытаться разбить ваш код на дополнительные вспомогательные функции.

Одна из идей состоит в том, чтобы создать четыре функции (сложение, вычитание, умножение, деление), подобные этой:

def multiply(val1, val2):
    # Unpack the tuples.
    numerator1, denominator1 = val1
    numerator2, denoninator2 = val2

    # Figure out the resulting numerator and denominator here.

    # Return the result as a tuple.
    return numerator, denominator

Реорганизуйте ваш код, чтобы использовать вспомогательные функции, и я думаю, ваш основной код будет чище.

1
ответ дан 18 December 2019 в 09:47
поделиться

Вы можете использовать мемоизацию в функции euclid , которая может помочь ускорить работу в зависимости от входных данных. Однако это будет использовать больше памяти

. Вы также можете использовать присвоение кортежей в евклид

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

карта здесь быстрее

a, b, c, d = map(int, wyjscie[0].split("/")+wyjscie[2].split("/"))
1
ответ дан 18 December 2019 в 09:47
поделиться

Вероятно, самым большим улучшением, которое вы могли бы сделать, было бы использование библиотеки Python (2.6) fractions :

>>> import fractions
>>> fractions.Fraction(1,7) + fractions.Fraction("3/5")
Fraction(26, 35)
9
ответ дан 18 December 2019 в 09:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: