2010-06-06 9 views
6

Zasadniczo potrzebuję, aby program działał jak prosty kalkulator frakcji (dodawanie, odejmowanie, mnożenie i dzielenie) dla pojedyncza linia wejścia, na przykład:
-input: 1/7 + 3/5
-Output: 26/35Porady dotyczące tworzenia kodu kalkulatora frakcji bardziej zoptymalizowanego (szybszego i mniejszego wykorzystania pamięci)

Mój początkowy kod:

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) 

Który ja zmniejszona do:

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))])) 

Każda rada na temat tego, jak poprawić to dalej, jest mile widziana.

Edycja: jeszcze jedna rzecz, o której zapomniałem wspomnieć - kod nie może korzystać z żadnych bibliotek poza sys.

+0

Czy to zadanie domowe? –

+0

Tak, jest. Pamiętaj, że nie potrzebuję kompletnego rozwiązania. To, czego szukam, to ogólne wskazówki, które można zastosować w tym przypadku. –

+1

przez wywołanie 'euclid (a * d, b * c)' wiele razy prawdopodobnie zrobiłeś wolniej niż wersja, która przechowuje wynik w zmiennej –

Odpowiedz

5

bym utworzyć klasę zawierającą numerator i denominator pola (obie liczby) oraz wdrożenie __add__, __sub__, __mul__ i __div__ metod. Następnie możesz po prostu użyć zwykłych funkcji matematycznych, aby połączyć instancje.

Może to być przesada do twoich celów, ale kod będzie dużo czystszy.

W rzeczywistości podejście klasowe jest dokładnie tym, w jaki sposób wdrażany jest moduł fractions. Normalnie sugerowałbym zbadanie kodu źródłowego modułu frakcji, aby zobaczyć, jak jest napisany, ale ponieważ jest to praca domowa, nie jestem pewien, czy byłoby to dozwolone. Może warto sprawdzić po zakończeniu zadania, aby zobaczyć, jak implementowany jest pełnowymiarowy typ ułamkowego numeru.

+1

+1 Myślę, że dobrze napisany kod innych ludzi jest prawdopodobnie jednym z najlepszych sposobów nauki pisania kodu. Powinieneś koniecznie przyjrzeć się źródłu modułu 'ułamków' w pewnym momencie, ponieważ jest on prawdopodobnie bardzo dobrze napisany. – MatrixFrog

+0

Świetne punkty! Na pewno spróbuję zrozumieć, jak to się dzieje w module frakcji. Jak powiedział Daniel, może to być trochę przesada, ale z pewnością nie jest to marnotrawstwo. Dziękuję Ci. –

9

Prawdopodobnie największą poprawę można zrobić byłoby użyć Python (2.6) 's fractions biblioteka:

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

To prawdopodobnie wykonałoby zadanie, gdyby nie fakt (o którym zapomniałem wspomnieć - przepraszam!), Że nie mogę używać żadnych bibliotek poza sys. –

1

Można czynnik poza kodu, który redukuje część do najniższych kategoriach od osobnika «+» , '-', itp. To powinno uczynić kod nieco czystszym i bardziej zwartym i czytelnym.

1

Możesz użyć memoization na funkcji euclid, która może przyspieszyć działanie w zależności od danych wejściowych. Jednak będzie to więcej pamięci

Można również użyć zadanie krotka w euclid

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

mapie jest szybsze tutaj

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

Algorytm Euclida wykonuje kroki O (log n), więc jego zapamiętanie nie pomoże wiele. Co więcej, wiele danych wejściowych może nigdy nie zostać powtórzonych, więc zapamiętywanie będzie po prostu powoli przeciekało pamięć, gdy program jest już uruchomiony. –

+1

Zawsze możesz spróbować go zapamiętać i nie pamiętać, aby zobaczyć, który z nich jest szybszy. Przypuszczam, że używanie modułu timeit (http://docs.python.org/library/timeit.html) byłoby dopuszczalne, pomimo reguły przeciwko korzystaniu z bibliotek. – MatrixFrog

1

Faktoring się euclid do funkcji pomocnika jest dobrym pomysłem. Sugerowałbym próbę dalszego podzielenia kodu na dodatkowe funkcje pomocnicze.

Jednym z pomysłów jest stworzenie czterech funkcji (dodawanie, odejmowanie, mnożenie, dzielenie), jak ten:

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 

byłaby kodu do korzystania z funkcji pomocniczych i myślę, że głównym kod będzie czystsze.

0

Można również zoptymalizować funkcję euklidesową. Zamiast używać algorytmu Euclida, możesz użyć Binary GCD.

Dwa sposoby wdrożenia algorytmu można znaleźć here, niestety kod jest w C. Wciąż nie sądzę, że jest to trudne, jeśli przetłumaczyć go na python.

Powiązane problemy