2010-06-06 4 views
6

Grundlegend, was ich für das Programm brauche, ist ein so einfacher Bruchrechner (für Addition, Subtraktion, Multiplikation und Division) für die a einzige Zeile eingegeben werden, zum Beispiel:
-input: 1/7 + 3/5
-Ausgang: 26/35Tipps, um einen Fraktionsrechner-Code optimierter zu machen (schneller und mit weniger Speicher)

Meine anfängliche Code:

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) 

die ich reduziert:

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

Alle Ratschläge, wie Sie dies weiter verbessern können, sind willkommen.

Bearbeiten: eine weitere Sache, die ich vergessen zu erwähnen - der Code kann keine Bibliotheken außer sys verwenden.

+0

Ist das Hausaufgaben? –

+0

Ja, ist es. Bitte beachten Sie, dass ich keine vollständige Lösung benötige. Was ich suche, sind allgemeine Tipps, die in diesem Fall angewendet werden können. –

+1

durch den Aufruf 'euclid (a * d, b * c)' mehrere Male haben Sie wahrscheinlich langsamer als die Version, speichert das Ergebnis in einer Variablen –

Antwort

5

würde ich eine Klasse enthält numerator und denominator Felder (beide ganze Zahlen sind) und die Umsetzung __add__, __sub__, __mul__ und __div__ Methoden erstellen. Dann können Sie einfache mathematische Funktionen verwenden, um die Instanzen zu kombinieren.

Es könnte für Ihre Zwecke übertrieben sein, aber der Code wird viel sauberer sein.

In der Tat ist der klassenbasierte Ansatz genau wie das fractions Modul implementiert ist. Normalerweise würde ich vorschlagen, den Quellcode des Bruchmoduls zu prüfen, um zu sehen, wie es geschrieben ist, aber da dies für Hausaufgaben ist, bin ich mir nicht sicher, dass das erlaubt wäre. Es könnte sich lohnen, nach Beendigung der Zuweisung auszuchecken, nur um zu sehen, wie ein vollwertiger Bruchzahl-Typ implementiert wird.

+1

+1 Ich denke, den gut geschriebenen Code anderer Leute zu lesen ist wahrscheinlich eine der besten Möglichkeiten, um zu lernen, wie man Code gut schreibt. Sie sollten sich auf jeden Fall die Quelle des Moduls 'Brüche' ansehen, da es wahrscheinlich sehr gut geschrieben ist. – MatrixFrog

+0

Tolle Punkte dort! Ich werde auf jeden Fall versuchen zu verstehen, wie es im Modul "Brüche" gemacht wird. Wie Daniel sagte, es könnte ein bisschen Overkill sein, aber das ist sicherlich keine Verschwendung. Vielen Dank. –

9

Wahrscheinlich die größte Verbesserung, die Sie Python machen könnte, wäre zu verwenden (2,6) 's fractions Bibliothek:

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

Das würde wahrscheinlich den Job erledigen, wenn es nicht wegen der Tatsache wäre (die ich vergessen habe zu erwähnen - Entschuldigung!), Dass ich außer sys keine Bibliotheken benutzen kann. –

1

Sie könnten den Code ausklammern, die den Anteil zu niedrigsten Begriffe aus den einzelnen reduziert ‚+‘ , '-' usw. Das sollte den Code ein wenig sauberer und kompakter und lesbarer machen.

1

Sie könnten memoization auf der euclid Funktion verwenden, die helfen kann, abhängig von den Eingabedaten zu beschleunigen. Dies wird jedoch mehr Speicherplatz

Sie können auch ein Tupel Vergabe in euclid

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

Karte ist schneller hier

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

Der Algorithmus von Euklid benötigt O (log n) Schritte, so dass das Memoisieren nicht viel hilft. Darüber hinaus werden viele der Eingaben möglicherweise nie wiederholt, so dass Memo-Speicher nur langsam Speicher verliert, je länger das Programm läuft. –

+1

Sie könnten es immer Memoized und Non-Memoized versuchen, um zu sehen, welche schneller ist. Ich nehme an, dass das Timeit-Modul (http://docs.python.org/library/timeit.html) trotz der Regel gegen die Verwendung von Bibliotheken akzeptabel ist. – MatrixFrog

1

Factoring aus euclid in eine Hilfsfunktion ist eine gute Idee. Ich würde vorschlagen, dass Sie versuchen, Ihren Code in weitere Hilfsfunktionen aufzuteilen.

Eine Idee ist, vier Funktionen zu erstellen (addieren, subtrahieren, multiplizieren, dividieren) wie diese:

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 

Refaktorieren Code, um die Hilfsfunktionen zu verwenden, und ich denke, Ihr Haupt Code sauberer sein wird.

0

Sie können auch die euclid-Funktion optimieren. Anstatt den Euclid-Algorithmus zu verwenden, können Sie Binary GCD verwenden.

Zwei Möglichkeiten, den Algorithmus zu implementieren, finden Sie here, leider ist der Code in C. Noch denke ich nicht, ist das schwer, wenn Sie es in Python übersetzen.

Verwandte Themen