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.
Я бы создал класс, содержащий поля numerator
и denominator
(оба целые числа) и реализующий методы __add__
, __sub__
, __mul__
и __div__
. Затем вы можете просто использовать обычные математические функции для объединения экземпляров.
Это может быть излишеством для ваших целей, но код будет намного чище.
На самом деле, подход на основе классов - это именно то, как реализован модуль дробей
. Обычно я бы предложил изучить исходный код модуля дробей, чтобы посмотреть, как он написан, но поскольку это домашнее задание, я не уверен, что это разрешено. Возможно, стоит посмотреть после выполнения задания, чтобы увидеть, как реализован полноценный тип дробных чисел.
Вы можете убрать код, который сводит дробь к наименьшим членам из отдельных '+', '-' и т.д. Это сделает код немного чище, компактнее и читабельнее.
Вычленение на множители евклида
во вспомогательную функцию - хорошая идея. Я бы посоветовал попытаться разбить ваш код на дополнительные вспомогательные функции.
Одна из идей состоит в том, чтобы создать четыре функции (сложение, вычитание, умножение, деление), подобные этой:
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
Реорганизуйте ваш код, чтобы использовать вспомогательные функции, и я думаю, ваш основной код будет чище.
Вы можете использовать мемоизацию в функции 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("/"))
Вероятно, самым большим улучшением, которое вы могли бы сделать, было бы использование библиотеки Python (2.6) fractions
:
>>> import fractions
>>> fractions.Fraction(1,7) + fractions.Fraction("3/5")
Fraction(26, 35)