Erstes Programm. 8 Bit Operator

Code-Stücke können hier veröffentlicht werden.
Antworten
new_bee
User
Beiträge: 3
Registriert: Sonntag 26. August 2018, 16:27

Hallo @all, bin Programmier-Neuling. Hier mein erstes echtes Programm, bestehend aus zwei Modulen.
Das Programm ist dazu gedacht, logische Operationen an 8-bit langen binären Zahlen durchzuführen (in Zweierkomplement-Darstellung). Für die Ausführung der Funktion hauptprogramm() gibt es dann noch ein extra modul, in dem das hauptprogramm immer wieder aufgerufen wird, bis der Benutzer 'Exit' eintippt.

Modul #1

Code: Alles auswählen

#modul <funktion>

#Funktion zur Eingabeprüfung und Korrektur
def prüfung(eingangswert):
    prüfung_fehler = 0
    länge = len(eingangswert)
    korrigiert = ""
    for i in range(0,länge):
        zeichen = eingangswert[i]
        if zeichen != " ":
            korrigiert = korrigiert + zeichen

    länge = len(korrigiert)
    for i in range(0,länge):
        zeichen = korrigiert[i]
        if zeichen != "1" and zeichen != "0":
            print("Error! Unexpected Input. Try again.")
            prüfung_fehler = 0
            break
        else:
            prüfung_fehler = 1
    if länge != 8:
        print("Error! Unexpected Length. Operand has to be",
              "8 Bits long.")
        prüfung_fehler = 0
    return prüfung_fehler, korrigiert
#Funktion zur Umwandlung des 8 Zeichen langen strings in
#die entsprechende dezimale Integer
def umwandlung(string):
    dezimalzahl = 0
    if string[0] == "0":
        for i in range(1,8):
            gesetzt = string[i]
            bitpos = 7 - i
            if gesetzt == "1":
                dezimalzahl += (2**bitpos)

    else:
        for i in range(1,8):
            gesetzt = string[i]
            bitpos = 7 - i
            if gesetzt == "0":
                dezimalzahl += (2**bitpos)
        dezimalzahl = -(dezimalzahl + 1)
    return dezimalzahl
#funktion zur operatorauswahl
def operator(wahl):
    operator_fehler = 0
    op = -1
    if wahl == "And" or wahl == "1":
        operator_fehler = 1
        op = 0
    elif wahl == "Or" or wahl == "2":
        operator_fehler = 1
        op = 1
    elif wahl == "Xor" or wahl == "3":
        operator_fehler = 1
        op = 2
    elif wahl == "Inv" or wahl == "4":
        operator_fehler = 1
        op = 3
    elif wahl == "Move>>" or wahl == "5":
        operator_fehler = 1
        op = 4
    elif wahl == "Move<<" or wahl == "6":
        operator_fehler = 1
        op = 5
    else:
        print("Error! Choose correct operator.")
    return operator_fehler, op
#funktion um integer in binäres zweierkomplement(8 Bit) zu verwandeln
def umwandlung_zurück(dezimal):
    if 127 >= dezimal >= 0:
        bit8 = bin(dezimal)
        bit8 = str(bit8)
        bit8 = bit8[2:] # 0b wegschneiden
        länge = len(bit8)
        zusatz = 8 - länge
        bit8 = "0"*zusatz + bit8
    elif 0 > dezimal >= -128:
        bit8 = bin(dezimal+1)
        bit8 = str(bit8)
        bit8 = bit8[3:] # -0b wegschneiden
        länge = len(bit8)
        neubit8 = ""
        for i in range(0,länge):
            if bit8[i] == "0":
                neubit8 += "1"
            else:
                neubit8 += "0"
        bit8 = neubit8
        zusatz = 8 - länge
        bit8 = "1"*zusatz + bit8
    else:
        bit8 = "--xx--xx"
        print("Result is longer than 8 bits.")
    return bit8
Modul #2

Code: Alles auswählen

# 8 Bit operator hauptprogramm
import funktion

def hauptprogramm():
    fehler = 0
    while fehler == 0:
        print("Bits, please:")
        eingabe = input()
        analyse, rückgabe = funktion.prüfung(eingabe)
        fehler = analyse

    operand1 = funktion.umwandlung(rückgabe)

    fehler = 0
    while fehler == 0:
        print("Choose operator. Possible: And[1], Or[2],",
              "Xor[3], Inv[4], Move>>[5], Move<<[6]")
        eingabe1 = input()
        analyse1, opwahl = funktion.operator(eingabe1)
        fehler = analyse1
#herausfinden, ob zweiter operand benötigt wird
#anhand der operatorauswahl
    if opwahl in [0,1,2]:
        fehler = 0
        while fehler == 0:
            print("Bits, please:")
            eingabe2 = input()
            analyse2, rückgabe2 = funktion.prüfung(eingabe2)
            fehler = analyse2
        operand2 = funktion.umwandlung(rückgabe2)
    #operation durchführen abhängig von operatorwahl
        if opwahl == 0:
            ergebnis_dezimal = operand1 & operand2
        elif opwahl == 1:
            ergebnis_dezimal = operand1 | operand2
        else:
            ergebnis_dezimal = operand1 ^ operand2

#bei operator = inversion, inversion durchführen
    if opwahl == 3:
        operand2 = 0
        rückgabe2 = "xxNonexx"
        ergebnis_dezimal = ~operand1
#berechnung bei bits nach rechts schieben
    if opwahl == 4:
        operand2 = 0
        rückgabe2 = "xxNonexx"
        fehler = 0
        while fehler == 0:
            print ("How many Bits do want to move?")
            eingabe3 = input()
            try:
                anzahl_schieben = int(eingabe3)
                ergebnis_dezimal = operand1>>(anzahl_schieben)
                break
            except:
                print("Error! Integer expected.")
#berechnung bei bits nach links schieben
    if opwahl == 5:
        operand2 = 0
        rückgabe2 = "xxNonexx"
        fehler = 0
        while fehler == 0:
            print ("How many Bits do want to move?")
            eingabe3 = input()
            try:
                anzahl_schieben = int(eingabe3)
                ergebnis_dezimal = operand1<<(anzahl_schieben)
                break
            except:
                print("Error! Integer expected.")
#dezimales ergebnis in 8bit zweierkomplement verwandeln
    endergebnis = funktion.umwandlung_zurück(ergebnis_dezimal)
    print("Operand_1:", rückgabe, "   Dec:", operand1)
    print("Operand_2:", rückgabe2, "   Dec:", operand2)
    print("           --------        -----")
    print("Result:   ", endergebnis, "   Dec:", ergebnis_dezimal)
    
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo new_bee,

ein Modul das `funktion` heißt, ist etwas sehr allgemein. Was haben denn die Funktionen in diesem Modul als gemeinsamen Nenner?

Kommentare werden so weit eingerückt, wie der umgebende Block, damit man die Blöcke noch gut erkennen kann. Die Kommentare direkt vor den Funktionen solltest Du als Doc-Strings schreiben.

Für die Fehlerbehandlung nimmt man statt Rückgabeflags Exceptions. Über Indizes zu iterieren ist ein Anti-Pattern, da man auch direkt über die Elemente einer Liste oder eines Strings gehen kann.

Die erste Funktion könnte also so aussehen:

Code: Alles auswählen

def prüfung(eingangswert):
    """ Funktion zur Eingabeprüfung und Korrektur """
    korrigiert = ""
    for zeichen in eingangswert:
        if zeichen != " ":
            korrigiert += zeichen
    for zeichen in korrigiert:
        if zeichen != "1" and zeichen != "0":
            raise ValueError("Error! Unexpected Input. Try again.")
    if len(korrigiert) != 8:
        raise ValueError("Error! Unexpected Length. Operand has to be"
              " 8 Bits long.")
    return korrigiert
oder statt mit Schleifen mit höheren Funktionen:

Code: Alles auswählen

def prüfung(eingangswert):
    """ Funktion zur Eingabeprüfung und Korrektur """
    korrigiert = eingangswert.replace(" ", "")
    if set(korrigiert) - set("01"):
        raise ValueError("Error! Unexpected Input. Try again.")
    if len(korrigiert) != 8:
        raise ValueError("Error! Unexpected Length. Operand has to be 8 Bits long.")
    return korrigiert
Im Hauptprogramm benutzt Du nackte `except`s, man sollte aber immer den konkreten Fall abfangen, hier also ValueError. opwahl 4 und 5 sind fast identisch, so dass man sie zusammenfassen könnte. `fehler` wird innerhalb der Schleife nie geändert, so dass es eine `while True:`-Schleife ist.
new_bee
User
Beiträge: 3
Registriert: Sonntag 26. August 2018, 16:27

Also vielen Dank erst mal für dein feedback. Die Änderungen machen die Funktion schon mal ein Stück kürzer. Dass man das mit dem Leerzeichen entfernen ("korrigiert") so einfach umsetzen kann, wusste ich nicht. Das finde ich sehr gut. Und das mit dem raise ValueError kam in meinem Programmier-Lernbuch noch nicht dran. Da muss ich noch ein bisschen weiterlesen :lol: . Was meinst du mit "über indizes iterieren"? Generell, dass man i als "Schleifenvariable" benutzt oder dass ich hier i dann innerhalb der Schleife als index für die Slices benutzt habe? Weil in meinem Buch wird eigentlich jede Schleife mit i als Schleifenvariable "generiert".
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich meine damit, dass man überhaupt i oder irgendeine anderen Index als Schleifenvariable benutzt. Was man statt dessen macht, habe ich ja gezeigt.
new_bee
User
Beiträge: 3
Registriert: Sonntag 26. August 2018, 16:27

Ich habe jetzt die Rückgabeflags durch die ValueError Exceptions ersetzt und alles passt so weit. Aber nur mal so interessehalber: Gibt es Situationen, in denen ein Rückgabeflag sinnvoll wäre?
Antworten