Matrizen Addition - Manuelle Eingabe

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
Kampfkeiler
User
Beiträge: 9
Registriert: Montag 31. Oktober 2011, 20:54

Hallo,
folgendes Programm nimmt 2 Matrizen an (die Größe kann selbst bestimmt werden) und addiert diese dann.
Das Ergebnis der Addition soll dann ausgegeben werden.
Zumindest in der Theorie...
Sobald ich höhere Zahlen für die Spalten und Zeilen eingebe, bekomme ich eine Fehlermeldung:
IndexError: list index out of range
Weiß jemand woran das liegt? Mit kleineren Zahlen funktioniert das Programm ja.

Außerdem würde ich mich freuen, wenn mir jemand erklären könnte, was ich machen muss, damit der Nutzer sieht, für welche Zeile/Spalte er gerade den Wert angibt.

Code: Alles auswählen

def holeZahl(Zahlenprüfung):
    while True:
        try:
            return(int(input(Zahlenprüfung)))
        except:
            print("Das ist keine Zahl.")

def druckeMatrix(v):
    for x in v:
        print(x)

print("Dieses Programm addiert zwei Matrizen, die Sie manuell eingeben!")
print("Geben Sie die gewünschte Anzahl der Zeilen an: ")
Zeilen = holeZahl("Zeilen = ")
print("Geben Sie die gewünschte Anzahl der Spalten an: ")
Spalten = holeZahl("Spalten = ")
print("Anzahl Zeilen:", Zeilen)
print("Anzahl Spalten:", Spalten)

print(" ")

print("Es wird folgende Matrix erstellt:")
StartMatrix = [[0 for z in range(Zeilen)] for s in range(Spalten)]
druckeMatrix(StartMatrix)

print(" ")

print("Geben Sie nun die Werte der Matrix A an!")

A = [[int(input("Wert eingeben:")) for z in range(Zeilen)] for s in range(Spalten)]
print(" ")
print("Matrix A:")
druckeMatrix(A)

print(" ")

print("Geben Sie nun die Werte der Matrix B an!")

B = [[int(input("Wert eingeben:")) for z in range(Zeilen)] for s in range(Spalten)]
print(" ")
print("Matrix B:")
druckeMatrix(B)

print(" ")

C = [[A[z][s]+B[z][s] for s in range(Spalten)] for z in range(Zeilen)]
print("Ergebnis der Addition:")
druckeMatrix(C)
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

Vom Anschauen her scheint mir: Spalten- und Zeilen-Indizes sind bei der Addition vertauscht
Kampfkeiler
User
Beiträge: 9
Registriert: Montag 31. Oktober 2011, 20:54

Wenn ich die beiden dort Tausche stimmt das Ergebnis komischerweise nicht mehr...
BlackJack

@Kampfkeiler: Das hat sicher nichts mit der Grösse der Zahlen zu tun, sondern dass Du falsche Zahlen als Index verwendest. Und zwar stimmt es entweder bei der Eingabe nicht, oder bei Ausgabe und Berechnung von C. Du musst Dich halt entscheiden ob die äussere Liste eine Liste von Spalten oder von Zeilen sein soll. In der Hälfte des Programms so und in der anderen Hälfte anders, geht nicht.

Sonstige Anmerkungen: Bei der Ausnahmebehandlung sollte man kein „nacktes“ ``except:`` verwenden, sondern immer nur auf konkrete Ausnahmen reagieren. Sonst sitzt man früher oder später vor einem Quelltext der nicht funktioniert und wo man den Grund nicht findet, weil man eine Ausnahme nie zu Gesicht bekommt. Oder der Anwender ärgert sich, weil er zum Beispiel ein Programm nicht wie gewohnt mit Strg+C (Unices) oder Strg+Z (Windows) abbrechen kann.

Die Namensgebung hält sich nicht an PEP 8 -- Style Guide for Python Code. Und einige Namen sind schlecht gewählt. Bei mathematischen Programmen kann man mal von der Richtlinie abweichen, dass man keine Abkürzungen verwenden sollte, weil in dem Fachgebiet kurze Namen nicht unüblich sind, aber wenn es einen längeren, beschreibenden Namen gibt, sollte man ihn auch verwenden. `x` und `v` in `drucke_matrix()` könnte man zum Beispiel `zeile` und `matrix` nennen. Beziehungsweise die englischen Worte, denn so ein Durcheinander von Englisch/Deutsch bei den Bezeichnern ist IMHO unschön.

`Zahlenprüfung` ist ein schlechter Name, weil der so überhaupt nicht das beschreibt wofür er eigentlich steht. Da wird keine Zahlenprüfung übergeben, sondern der `prompt` für die Eingabeaufforderung.

Der Code für die Eingabe der beiden Matrizen wiederholt sich, das sollte man in einer Funktion erledigen, die man dann für jede Matrize einmal aufruft. Und vielleicht wäre es für den Benutzer schöner wenn er eine komplette Zeile von Zahlen durch Leerzeichen getrennt auf einmal eingeben könnte, statt für jede Zahl die Eingabetaste betätigen zu müssen.

Diese Indexerei bei Listen ist in Python unüblich, weil in den meisten Fällen unnötig. Man kann über Elemente von Listen und anderen „Container“-Objekten *direkt* iterieren, ohne einen Umweg über Indizes gehen zu müssen. Ungetestet:

Code: Alles auswählen

C = [[a + b for a, b in zip(row_a, row_b)] for row_a, row_b in zip(A, B)]
Wozu ist `StartMatrix` gut? Das wird nur ausgegeben, aber nirgends wirklich verwendet!?

Wenn Du dem Benutzer die aktuelle Zeile/Spalte anzeigen willst, dann musst Du das halt einfach *machen*. Ausgaben kann man mit `print()` tätigen. Aber das weisst Du ja schon, also wo ist das Problem?
Kampfkeiler
User
Beiträge: 9
Registriert: Montag 31. Oktober 2011, 20:54

BlackJack hat geschrieben:Du musst Dich halt entscheiden ob die äussere Liste eine Liste von Spalten oder von Zeilen sein soll. In der Hälfte des Programms so und in der anderen Hälfte anders, geht nicht.
Wenn ich Zeile und Spalte bei C ändere, dann stimmt die Lösung aber nicht mehr.
Und vielleicht wäre es für den Benutzer schöner wenn er eine komplette Zeile von Zahlen durch Leerzeichen getrennt auf einmal eingeben könnte, statt für jede Zahl die Eingabetaste betätigen zu müssen.
Wir haben folgende Aufgabe: "Der Anwender muss zu jedem Eingabewert die Information
erhalten, in welcher Zeile und Spalte er sich gerade befindet:
A[2][3] = …"
Wenn Du dem Benutzer die aktuelle Zeile/Spalte anzeigen willst, dann musst Du das halt einfach *machen*. Ausgaben kann man mit `print()` tätigen. Aber das weisst Du ja schon, also wo ist das Problem?
Aber wie bekomme ich das hin, dass es automatisch die richtige Zeile und Spalte wie oben beschrieben angibt?
Das muss doch dann in der Zeile:

Code: Alles auswählen

B = [[int(input("Wert eingeben:")) for z in range(Zeilen)] for s in range(Spalten)]
irgendwo untergebracht werden oder nicht?
BlackJack

@Kampfkeiler: Nur bei C ändern reicht ja auch nicht. Wenn Du C änderst, musst Du auch alle anderen Stellen ändern wo Du die Matrix als Spaltenliste und nicht als Zeilenliste behandelst. Alternativ, und das dürfte die bessere Lösung sein, könntest Du die Matrix als eine Liste mit Listen für die Zeilen speichern. Du musst Dich für eine der beiden Möglichkeiten entscheiden und dass dann auch *überall* gleich handhaben.

Die Zeilen-/Spaltennummer kannst Du in der „list comprehension“ unterbringen. Da wo jetzt ``"Wert eingeben:"`` steht muss halt eine Zeichenkette erstellt werden, welche die aktuellen Koorodinaten enthält. Zeichenketten und wie man dort Werte hinein formatiert, sollten im Python-Tutorial in der Dokumentation behandelt werden. Das geht mit dem ``%``-Operator oder der `format()`-Methode auf Zeichenketten.

Wenn das mit den Koordinaten so in der Aufgabe vorgegeben ist, dann musst Du das wohl so lösen, aber ich finde diese Eingabeform etwas benutzerunfreundlich.
Kampfkeiler
User
Beiträge: 9
Registriert: Montag 31. Oktober 2011, 20:54

BlackJack hat geschrieben: Wenn Du C änderst, musst Du auch alle anderen Stellen ändern wo Du die Matrix als Spaltenliste und nicht als Zeilenliste behandelst.
Wenn ich C ändere, dann sind doch alle gleich oder übersehe ich da was?
Das geht mit dem ``%``-Operator oder der `format()`-Methode auf Zeichenketten.
Hab mir das mal im Tutorial angeschaut, aber ich wüsste nicht, wie ich das so bei mir einbauen könnte, dass der automatisch die aktuelle Position angibt.
BlackJack

@Kampfkeiler: Wenn Du nur C änderst, dann gibt es noch eine andere Stelle im Programm, welche die Matrix als Liste von Zeilenlisten behandelt. Schau Dir noch mal meinen ersten Tipp bezüglich der Namensgebung an. Aber wie gesagt, die andere Richtung — die Matrix als Liste von Listen mit Zeilenwerten zu behandeln, erscheint mir „natürlicher“ und einfacher. Du solltest also nicht C ändern sondern die Stellen wo Du es anders herum als bei C machst. Bei den Fragen weiter unten sollte nachdenken über die 3. hier hilfreich sein.

Zur Koordinatenangabe: Das ganze in drei einfache Fragen herunter gebrochen, die Du eigentlich beantworten können müsstest, und die zusammen die Lösung ergeben:

1. Wenn man die Koordinaten an Namen gebunden hat, wie würde dann der Ausdruck aussehen um die in eine Zeichenkette hinein zu formatieren?

2. An welche Namen innerhalb der verschachtelten „list comprehension“ (LC) sind die Koordinaten gebunden?

3. Wie würde die verschachtelte LC ohne die LC-Syntax aussehen, also ausführlich als ``for``-Schleifen formuliert? (Diese Frage deckt auf, ob Du LCs grundsätzlich verstanden hast.)

Zeichenkettenformatierung wird im Tutorial anscheinend nicht beschrieben, aber bei Zeichenketten ist dort am Ende ein Link zu dem entsprechenden Abschnitt in der Dokumentation. LCs und verschachtelte LCs werden im Tutorial ausführlich mit Beispielen und Äquivalenzen behandelt.
Kampfkeiler
User
Beiträge: 9
Registriert: Montag 31. Oktober 2011, 20:54

Ich verstehe es nicht. Ich bekomme das einfach nicht hin.
Ich habe das jetzt mit format() versucht. Dafür habe ich folgende Definition gemacht:

Code: Alles auswählen

def Position(Spalten,Zeilen):
    for X in range(1,Zeilen+1):
        for Y in range(1,Spalten+1):
            print([X],[Y])
Jetzt wollte ich das dort einbauen wo "Wert eingeben" stand:

Code: Alles auswählen

A = [[int(input("{} =".format(Position(Spalten,Zeilen)))) for s in range(Spalten)] for z in range(Zeilen)]
Ich habe keine Ahnung wie das gehen soll. Hab ich format() vollkommen falsch verwendet? Wie muss ich es eingeben?
BlackJack

@Kampfkeiler: Ja du hast `format()` falsch verwendet. Und Funktionen offensichtlich nicht verstanden. Genau so wenig wie „list comprehensions“ (LCs). Deine `Position()`-Funktion gibt gar nichts zurück, dafür aber bei *jedem* Aufruf *alle* Positionen in einelementige Listen die in einem Tupel stecken auf die Standardausgabe aus. Das sieht eher nach wildem rumprobieren als nach durchdachtem Vorgehen aus. Dir ist anscheinend nicht einmal der Unterschied zwischen den verschiedenen Datentypen wie Zeichenkette, Tupel, oder Liste klar.

Am besten fängst Du noch einmal von vorne an mit dem Durcharbeiten eines Tutorials für die Grundlagen.

Edit: Beantworte zum Beispiel mal 1. von meinen Fragen. Mit Quelltext der das, und nur genau das macht. Binde zwei beliebige Zahlen an zwei verschiedene Namen und dann gibt etwas in der Form ``'A[j]'`` aus, wobei die Werte für i und j über `format()` in die Zeichenkette hinein formatiert werden.

Dann beantworte die zweite Frage, wobei es dafür nötig sein kann erst die dritte zu beantworten. Und dann solltest Du die Lösung haben.
Antworten