Binäre-Zahl-Calculator: Zahl auf unzulässige Zeichen prüfen.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
MrBrightside
User
Beiträge: 10
Registriert: Dienstag 14. November 2017, 16:01

Hallo zusammen,

ich programmiere zurzeit einen Rechner der binäre in dezimale Zahlen umrechnet und umgekehrt.
Meinen Quellcode:

Code: Alles auswählen


#Funktionen
#------------------------------------------------------------------
def calc_bin():
    bin_num=input("Geben Sie eine binäre Zahl ein: ") #Eingabe einer beliebig langen Binären Zahl.

    solution=0 #Vorbereitung von verwendeten Variablen.
    counter=1
    add_num=1
    i=0
    while i < len(bin_num):  #Anzahl der Schleifendurchläufe ist gleich Anzahl der Stellen der binären Nummer.
        if bin_num[-counter] == "1": #Jede Stelle der Binären Nummer wird angelaufen und geprüft ob diese "1" ist oder nicht.
            solution=solution+add_num #Wenn die Stelle "1" ist, wird der entsprechende Wert zu der Lösung addiert.
        counter=counter+1 #Counter um die Stelle in der binären Zahl zu bestimmen.
        add_num=add_num*2 #Wert, der der Stelle in den binären Nummer entspricht. (Stelle 4 = Wert 8, usw.)
        i=i+1  #Counter für die Schleife.
    print("|======================\n|  Binär: {}\n|----------------------\n|  Dezimal: {}\n|======================\n".format(bin_num, solution))

def calc_dec():
    dec_num=int(input("Geben Sie eine dezimale Zahl ein: \n")) #Eingabe der dezimalen Zahl.
    counter=0 #Vorbereitung der Variablen
    i=1
    solution=0
    dec_num_or=dec_num #Speichern der eingebenen Zahl in einer zweite Variable damit diese im Ergebnismit angezeigt wird.
    while dec_num >= i:  #In dieser Schleife wird ermittelt, welches der höchte Wert in der binären Tabelle
        i=i*2  #ist, welcher noch von der Zahl abgezogen werden kann. Entsprechend dient die
        counter=counter+1  #Schleife dazu, die länge der binären Zahl zu ermitteln.
        
    solution="0"*counter #Der Lösungs-String wird generiert und mit "0" befüllt, damit die einzelnen Stellen angesprochen werden können.
    o=counter #Zweiter Counter damit die nächste Schleife funktioniert.

    while counter > 0: #Ermittlung welche Stellen der binären Zahl mit "1" befüllt werden.
        i=i/2 #Wert der Stelle in der binären Zahl.

        if dec_num >= i:  #Nur ausführen, wenn es bei der dezimalen Zahl noch einen Rest gibt.
            solution=solution[:o-counter]+"1"+solution[o-counter+1:]#Eintragung der veränderten Lösung in die Lösungsvariable.
            dec_num=dec_num-i #Reduktion der dezimalen Zahl um den ermittelten Wert.
        counter=counter-1

    print("|======================\n|  Dezimal: {}\n|----------------------\n|  Binär: {}\n|======================\n".format(dec_num_or, solution))

#Ablauf
#------------------------------------------------------------------
running = "y"
while running == "y":
    print("Eingabe von\n     a) Dezimaler Zahl\n     b) Binärer Zahl\n")
    choice=""
    while choice not in ("a", "b"):
        choice=input("Wählen sie \"a\" oder \"b\" aus: ")
    if choice == "a":
        calc_dec()
    else:
        calc_bin()
    running=""
    while running not in ("y", "n"):
        running=input("\nNeue Rechnung? (y/n)")
        if running == "y":
            print("\n"*50)
        
Die Umrechnung der Zahlen funktioniert, solange der Anwender korrekte Angaben macht. Es ist aber noch möglich, den Rechner mit Buchstaben oder Zahlen ungleich "0" und "1" zu füttern.
Konzentrieren wir uns erstmal auf die Funktion "calc_bin".

Code: Alles auswählen

def calc_bin():
def calc_bin():
    bin_num=input("Geben Sie eine binäre Zahl ein: ")

    solution=0
    counter=1
    add_num=1
    i=0
    while i < len(bin_num):
        if bin_num[-counter] == "1":
            solution=solution+add_num
        counter=counter+1
        add_num=add_num*2
        i=i+1
    print("|======================\n|  Binär: {}\n|----------------------\n|  Dezimal: {}\n|======================\n".format(bin_num, solution))
Meine Idee war, das Problem mit einer while-Schleife oder If-Anweisungen zu lösen.

Code: Alles auswählen

def calc_bin():
   bin_num=input()
   if bin_num includes <> "0" or "1":
      proceed
   else:
      calc_bin()
oder

Code: Alles auswählen

def calc_bin():
   bin_num=""
   while bin_num includes <> "0" or "1":
      bin_num=input()
      ...
      ...
Das Problem, das ich nicht lösen kann ist, wie genau kann ich jede Stelle einzeln prüfen? Das Programm muss auf jedes Zeichen der binären Nummer gucken und sobald es ein Zeichen entdeckt, das keine "1" oder "0" ist, eine neue Zahl fordern.

Bin ich auf dem richtigen Weg oder gibt es einfachere Möglichkeiten? Vielleicht kann mir ja jemand weiterhelfen.
Natürlich kann der Code gerne bewertet und Verbesserungsvorschläge gemacht werden, allerdings bitte ich darum das sich auf mein Problem konzentriert wird.

Vielen dank :-)
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

dir ist klar, dass Python das mit Bordmitteln kann, über die Build-Ins ìnt()`und `bin()`

Der Code ist in teilen ziemlich konfus und durch die Kommentarflut extrem schlecht zu lesen.

Zum eigentlichen Programm: Mach' aus der Eingabe ein Set und prüft, ob das Set nur aus 1 und 0 oder nur 1 besteht.

Gruß, noisefloor
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@MrBrightside: so ziemlich alle Kommentare sind überflüssig, weil sie nur das offensichtliche beschreiben. Wenn Du eine Zeile Python nicht verstehst, dann hilft der der Kommentar auch nicht wirklich weiter. Der Kommentar in Zeile 2 "Funktionen" ist falsch, denn das, was Du da geschrieben hast, sind Codeabschnitte mit Namen, aber keine Funktionen. Funktionen haben Eingabeparameter und Rückgabewerte. In calc_bin: die while-Schleifen sind fast noch schlimmer als eine for-in-range-Schleife, über die Zeichen eines Strings iteriert man direkt. `i` und `counter` sind bis auf 1 identisch und damit eine von beiden überflüssig, eher beide. `calc_bin` ist ein irreführender Name, weil keine Binärzahl berechnet wird. `solution` ist eine Lösung, Du berechnest aber eine Zahl und findest keine Lösung.

Das ergibt also:

Code: Alles auswählen

def calc_bin():
    bin_num = input("Geben Sie eine binäre Zahl ein: ")
    number = 0
    add_num = 1
    for char in reversed(bin_num):
        if char == "1":
            number += add_num
        add_num *= 2
    print("Binär: {}\nDezimal: {}".format(bin_num, number))
Deutlich einfacher ist das Berechnen der Zahl von großen Stellen zu kleineren, hier mal als Funktion:

Code: Alles auswählen

def calc_bin(bin_num):
    number = 0
    for char in bin_num:
        number = number * 2 + (char == "1")
    return number
Bei calc_dec belegst Du `solution` mit einem Wert, der gar nicht benutzt wird. Weise nur dann Variablen einen Wert zu, wenn es einen sinnvollen Startwert gibt und auch erst dann, wenn sie gebraucht werden. Das Zusammenbauen des Strings ist sehr kompliziert. Da Strings nicht veränderbar sind, ist das Vorbelegen mit 0en wirklich eine blöde Idee. Du baust den String von links nach rechts auf, so dass Du einfach immer ein Zeichen anhängen kannst. Benutze Ganzzahldivision `//`.

Der Zwischenschritt wäre also:

Code: Alles auswählen

def calc_dec():
    dec_num = int(input("Geben Sie eine dezimale Zahl ein: \n"))
    digits = 0
    # In dieser Schleife wird die Länge der binären Zahl ermittelt
    i = 1
    while dec_num >= i:  
        i *= 2
        digits += 1
       
    result = ""
    residual = dec_num
    for _ in range(digits):
        i //= 2
        if residual >= i:
            # Nur ausführen, wenn das Bit gesetzt ist.
            result += "1"
            residual -= i
        else:
            result += "0"
 
    print("Dezimal: {}\nBinär: {}".format(dec_num, result))
Deutlich einfacher ist das Aufbauen des Strings von kleinen zu großen Ziffern, hier mal als Funktion:

Code: Alles auswählen

def calc_dec(dec_num):
    result = ""
    while dec_num > 0:
        dec_num, digit = divmod(dec_num, 2)
        result = ("1" if digit else "0") + result
    return result or "0"
Im Hauptprogramm: statt Variablen mit Dummy-Werten zu belegen, dass while-Schleifen loslaufen, benutzt man `while True:`-Schleifen mit einem Abbruchkriterium per break am Ende. Es gibt vier verschieden Arten, literale Strings anzugeben, so dass es eigentlich nie nötig ist, Anführungszeichen zu escapen; So sind Strings einfach besser lesbar.

Zu Deinem Problem: Du prüfst doch schon jedes Zeichen darauf, ob es eine "1" ist oder nicht. Wo ist dann das Problem auch noch auf "0" zu prüfen? Im Fehlerfall wird normalerweise eine Fehlermeldung ausgegeben, oder besser, eine Ausnahme (Exception) ausgelöst. Was soll ein `proceed` denn machen? `bin_num includes <> "0" or "1"` ist kein gültiges Python, wie es richtig geht, hast Du schon in Deinem Hauptprogramm gezeigt.
Benutzeravatar
MrBrightside
User
Beiträge: 10
Registriert: Dienstag 14. November 2017, 16:01

Vielen Dank für die Antworten.
Ich habe mir schon gedacht, das der Code noch sehr Amateurhaft aufgebaut ist, daher bin ich sehr dankbar für die vielen Ansätze.

Da habe ich dann ja wieder zu tun. Vielen Dank und schönes Wochenende.
Antworten