Matrix-Funktion (mit binären Werten) Output-Problem

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
MikeOrMichael
User
Beiträge: 16
Registriert: Mittwoch 22. Februar 2012, 20:37

Hallo Leute,
erstmal danke, dass ihr den Thread überhaupt angeklickt habt. Wir haben hier alle wenig Zeit, deshalb werde ich mich mit dem Wesentlichen beeilen:
Ich bin noch Schüler, muss aber für ein Projekt einen QR-Code Generator mit Python programmieren. Ich habe mir Python auto-didaktisch beigebracht. Ich habe es bereits geschafft, mit Hilfe von Funktionen wie char_bin(str) und msg_bin(str) ganze Buchstaben und Nachrichten in Binär umzuwandeln. Nun ist es so, dass die binären Werte in Matrizen eingeordnet werden müssen, die der Reader des Geräts beim lösen des Codes in der richtigen Reihenfolge liest, so dass:
1 Buchstabe = 8 Binärziffern = 1 Matrix aus acht
Ich habe das System verstanden, doch gibt die Funktion einen Null-Wert als Output heraus. Hier der Aussschnitt:

>>> basebin = '00000000' - Basis-Binärwert
>>> def char_bin(str): - Alphanum. Wert- ASCII Wert - Binär ( + Komplettierung der Länge auf 8 mit Basebin)
return basebin [:8 - len(bin(ord(str))[2:])] + bin(ord(str))[2:]

>>> def msg_bin(msg): - Schleife = Binärwert für Nachricht
return ''.join ([char_bin(str) for str in msg])

>>> let=int - Position des Buchstaben, der in die Matrix transformiert werden soll.
>>> pos = range(len(char_bin(msg[0]))) - Range des Loops beim Kreieren der Matrix: 8 Werte = 8 Nummern im Binärcode des Buchstaben
>>> matrix1 = [[ int, int], - Basismatrix
[ int, int],
[ int, int],
[ int, int]]
>>> nb = int - Wert in Pos, da 'int' Objekte nicht callable

Die Matrix soll so aussehen: (die Zahlen sind die Position der Werte im Binärcode des Buchstaben)

2 1 Einer nach links, dann diagonal links nach unten aufgefüllt.
4 3
6 5
8 7




>>> def mat_1 (let):
for nb in pos:
if nb % 2 == 0: - Werte linke Spalte gerade
n = 0
M =(nb- 1) / 2 - Die Funktion
m = int(M) - Wir brauchen nur den absoluten Wert, da Dezimalzahlen als Position nutzlos.
matrix1[m][n] = char_bin(msg[let])[nb]
return matrix1[m][n]
elif nb % 2 == 1: - Werte rechte Spalte ungerade
n = 1
M =(nb- 1) / 2
m = int(M)
matrix1[m][n] = char_bin(msg[let])[nb]
return matrix1[m][n]
return matrix1
>>> mat_1 (0)
'0'

:K Ich weiß leider nicht weiter. Es ist nicht so, dass ich das System der Rechnung nicht verstanden hätte, aber es liegt wohl ein technisches Problem vor (vom Aufbau her). Es wäre wirklich, wirklich schön, wenn mir jemand helfen könnte, da ich zunehmend unter Druch gerate, weil ich als einziger aus meienr Gruppe das rhalbwegs kann un ´d die Präsentationen (vor sehr vielen Leuten) immer näher rückt.
Ich wäre euch wirklich dankbar.

Danke, dass ihr bis zu diesem Punkt gelesen habt.
Schönen Abend,
Michael
BlackJack

@MikeOrMichael: Könntest Du das noch einmal in syntaktisch korrektem Python und in Code-Tags posten? Kommentare werden in Python nicht mit einem Minus-Zeichen eingeleitet. Und dass das ganze als Interpreter-Sitzung vorliegt und nicht als Quelltext für ein Modul macht das ganze auch nicht gerade einfacher nach zu vollziehen.

``let = int`` oder die `int`\s in der verschachtelten Liste die an `matrix1` gebunden wird, sind unsinnig. `int` ist ein Datentyp, Du willst aber Objekte dieses Typs und nicht den Typ selber verwenden. Das sieht so aus als würdest Du versuchen Namen einen Typ zu geben, die haben in Python aber keinen. Somit sind solche „Deklarationsversuche“ sinnfrei. Als Platzhalter für die Matrix könntest Du 0 oder `None` verwenden. Und `let` und `nb` werden überhaupt nicht verwendet — die beiden Zuweisungen kann man sich also komplett sparen und damit zwei Namen.

Das `mat_1()` (was soll eigentlich diese Eigenart an Namen eine 1 anzuhängen) keine Matrix zurück gibt, sollte eigentlich klar sein, oder? Beim ersten ``return`` wird schliesslich keine Matrix zurückgegeben.

Die Funktion sollte nicht einfach so auf `matrix1` und `msg` operieren. Das ist ziemlich undurchsichtig wenn Datenstrukturen verändert werden, die nicht als Argumente übergeben werden. Bei drei, vier Funktionen mag man das noch im Überblick behalten, aber wenn Programme wachsen steigt man sehr schnell nicht mehr durch solche Abhängigkeiten durch.

In der Funktion ist auch viel redundantes. Aufrufe und Rechnungen die in beiden Zweigen der ``if``/``elif``-Abfrage gemacht werden sollte man dort heraus ziehen. Funktionsaufrufe bei denen immer wieder das selbe heraus kommt, sollte man nur einmal machen. Die Bedingung bei ``elif`` testet genau das Gegenteil der Bedingung beim ``if`` — damit kann man sich den Test sparen und einfach ``else`` verwenden. Der Wert von `n` hängt ziemlich deutlich von dieser Bedingung ab.

`char_bin()` ist viel zu kompliziert. Zum auffüllen mit Nullen gibt es auf Zeichenketten eine Methode. Umwandeln in Binärdarstellung und auffüllen mit Nullen kann man sogar noch einfacher mit Zeichenkettenformatierung mit dem ``%``-Operator oder der `format()`-Methode auf Zeichenketten haben.
MikeOrMichael
User
Beiträge: 16
Registriert: Mittwoch 22. Februar 2012, 20:37

@BlackJack Tut mir leid für die Verständnis- bzw. Anfängerfehler. Wie gesagt, ich bin noch neu in dem Gebiet. Also zusammenfassend:
1. Platzhalter für die Matrix entwerder None oder 0.
2. Die Funktion mat_1 hat eine 1 dahinter weil es 4 Matrizentypen gibt, die benutzt werden.
3. Ich sollte die Argumente bei der Funktionseingabe erweitern.
4. Else anstatt elif.
5. Objekte keinen Datentyp zuweisen.

Ich habe jetzt die Änderungen vorgenommen und werde sie in Code posten (ich lasse char_bin und msg_bin mal weg, um ans Wesentliche zu kommen):

Code: Alles auswählen

>>> matrix1 = [[ None, None],
[ None, None],
[ None, None],
[ None, None]]
>>> let = 0
>>> pos = range(len(char_bin(msg[let])))
>>> def mat_1 (msg, let):
	matrix1 [0][1] =  char_bin(msg[let])[0]
	for int in pos[1:]:                                     # Wir schließen 0 aus.
		if int % 2 == 0:
			n = 0
			matrix1[int((int- 1)) / 2][n] = char_bin(msg[let])[int]
			return matrix1[int((int- 1)) / 2][n]
		else:
			n = 1
			matrix1[int((int- 1)) / 2][n] = char_bin(msg[let])[int]
			return matrix1[int((int- 1)) / 2][n]
		return matrix1
>>> mat_1 (msg, let)
Traceback (most recent call last):
  File "<pyshell#49>", line 1, in <module>
    mat_1 (msg, let)
  File "<pyshell#48>", line 10, in mat_1
    matrix1[int((int- 1)) / 2][n] = char_bin(msg[let])[int]
TypeError: 'int' object is not callable
Nun ist es ein anderes Problem. Diesmal verstehe ich es: er kann mir halt keinen Objekttypen zurückgeben. Mit int() brauche ich nur den Stamm des Wertes, sofern er potenziell dezimal ist. Hmm. Zum Vergleich nochmal der alte Code.

Code: Alles auswählen

>>> def mat_1 (let):
            for nb in pos:
                   if nb % 2 == 0:
                          n = 0
                          M =(nb- 1) / 2 
                          m = int(M)
                          matrix1[m][n] = char_bin(msg[let])[nb]
                          return matrix1[m][n]
                  elif nb % 2 == 1:
                          n = 1
                          M =(nb- 1) / 2
                          m = int(M)
                          matrix1[m][n] = char_bin(msg[let])[nb]
                          return matrix1[m][n]
                   return matrix1
>>> mat_1 (0)
'0'
Ich hoffe, jetzt ist es lesbarer :oops: .
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Es ist eine schlechte Idee eine Variable "int" zu nennen, insbesondere wenn man später die eingebaute Funktion int(n) zur Konvertierung eines Werts zu einer Ganzzahl nutzen will, weil diese dadurch "überschrieben" wird.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@MikeOrMichael: Was fällt dir hier auf?

Code: Alles auswählen

>>> int
<type 'int'>
>>> int('7')
7
>>> type(int)
<type 'type'>
>>> type(int('7'))
<type 'int'>
>>> int = 5
>>> type(int)
<type 'int'>
>>> type(int('7'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
In specifications, Murphy's Law supersedes Ohm's.
MikeOrMichael
User
Beiträge: 16
Registriert: Mittwoch 22. Februar 2012, 20:37

@pillmuncher
'7' ist ein Integer und kann mit der Funktion int() verbunden werden, ohne dass sich der Typ ändert.
int = 5 ist jedoch eine Variable names int, der ein Integer (5) zugewiesen wurde.
Somit ändert sich die Bedeutung von int, da dies keine Funktion bzw. Typ mehr ist, sondern eine Variable.

Aha. Durch das Benutzen der "Int in Pos" in der Matrixfunktion ändert sich die Defintion der Funktion int() in die Variable um, weil sie den selben Namen haben...
Hmm, wie wäre es damit:

Code: Alles auswählen

>>> nb = int
>>> def mat_1 (msg, let):
        matrix1 [0][1] =  char_bin(msg[let])[0]
        for nb in pos[1:]:                                     # Wir schließen 0 aus.
                if nb % 2 == 0:
                        n = 0
                        matrix1[int((nb- 1)) / 2][n] = char_bin(msg[let])[nb]
                        return matrix1[int((nb- 1)) / 2][n]
                else:
                        n = 1
                        matrix1[int((nb- 1)) / 2][n] = char_bin(msg[let])[nb]
                        return matrix1[int((nb- 1)) / 2][n]
                return matrix1
Das hat sehr geholfen, danke :P !
Zum Hauptproblem zurück: Könnte es sein, dass die Funktion den Loop nicht richtig erfüllt ? Wenn nur der Wert 0 rauskommt (siehe alter Code), könnte es sein, dass er nur einen Wert nimmt, anstatt alle ? Ich vermute mal:
1. Er nimmt einen Wert, gibt matrix 1 [...][...] aus, macht dies nicht für die ganze Funktion, oder...
2. Er geht zur return matrix1 (die ganze Matrix) runter, und diese, unverändert, entspricht 0 (d.h er überspringt else/if).
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ich habe mal die ganzen verwirrenden Kommentare weggelassen und ein paar Namen verändert. char_bin() habe ich neu geschrieben, da das eingebaute String Formatting schon mitbringt, was du mühsam nachprogrammierst. Funktioniert aber leider erst ab Python 2.6. mat_1() habe ich vereinfacht:

Code: Alles auswählen

basebin = '00000000'

def char_bin(char):
    return '{0:0>8b}'.format(ord(char))

def msg_bin(msg):
    return ''.join(char_bin(char) for char in msg)

let = int  #  was ist das ?

pos = range(len(char_bin(msg[0])))  # woher kommt msg? Und was soll pos darstellen?

matrix1 = [
    [int, int],    #  was sollen die ganzen ints ?
    [int, int],
    [int, int],
    [int, int]
]

nb = int  #  was ist das ?

def mat_1(let):
    for nb in pos:
        n = nb % 2:
        m = int((nb - 1) / 2)
        matrix1[m][n] = char_bin(msg[let])[nb]
    return matrix1
Das if-Statement war unnötig, da n = 0 genau dann wenn nb % 2 == 0, bzw. n = 1 genau dann wenn nb % 2 == 1 war. Also kann man es direkt zuweisen. Alles andere in den jeweiligen Zweigen des if-Statements war sowieso identisch und hätte ausgelagert gehört.

Das Problem bei deinem mat_1() war, dass du schon an Ende vom ersten Schleifendurchlauf ein return matrix1[m][n] stehen hattest. Das hat die Funktion beendet und den Wert zurückgegeben, der gerade in matrix1[m][n] gespeichert war.

Außerdem: Abgesehen davon, dass deine Variablennamen völlig unverständlich sind, verwendest du globale Variablen, was praktisch immer eine sehr schlechte Idee ist. Mach lieber sowas:

Code: Alles auswählen

def mat_1(pos, msg, let):
    result = [  # immer noch: ?????
        [int, int],
        [int, int],
        [int, int],
        [int, int],
    ]
    for nb in pos:
        n = nb % 2:
        m = int((nb - 1) / 2)
        result[m][n] = char_bin(msg[let])[nb]
    return result
Das funktioniert zwar vermutlich immer noch nicht, denn was pos und let darstellen sollen, ist mir bisher nicht klar geworden. Aber vielleicht kannst du von hier aus etwas programmieren, was nicht ganz so verwirrt-verwirrend aussieht.
In specifications, Murphy's Law supersedes Ohm's.
MikeOrMichael
User
Beiträge: 16
Registriert: Mittwoch 22. Februar 2012, 20:37

Let = int ist die Position des Buchstabens, der umgewandelt bzw. in die Matrix in Binär aufgenommen werden soll.
Let = Letter

Pos = Position. Der Int-Wert, der die Anzahl der Ziffern pro umgewandelten Buchstaben in Binär angeben soll (immer 8, also [0:7]. Jede Ziffer mit dem Wert pos in char_bin(msg) soll halt an einen bestimmten Punkt in der Matrix).
msg = message / Einfach die Nachricht, die du umwandeln willst.

Die "ints" in der Matrix sind halt die Platzhalter für die kommenden Zahlen des Binärcodes des Buchstaben der Position let (sprich char_bin(let)).

Klasse, das mit n und dem Modulo-Ergebnis wäre mir nicht aufgefallen, danke !

Also sollte ich die leere Matrix als lokale Variable benutzen ? Okay.
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Ich verstehe immer noch nichts. Könntest du mal bitte in schönstem Pseudo-Code niederschreiben wie alles funktionieren soll?
Antworten