Hallo,
ich müsste einen string in eine checksum umwandeln.
Vorgegeben wird mir, dass es "crc-32 signed int" sein soll.
Also bin ich beim googlen auf folgendes gestoßen:
https://docs.python.org/3.6/library/binascii.html
Leider ist das was mir binascii.crc32(string.encode()) ausgibt, aber offenbar ein "unsigned long". In Python 2 war es wohl noch ein signed int.
In der Doku steht, man müsse " & 0xffffffff" dranhängen, damit es unter allen Python Versionen gleich ist.
Doch damit komme ich auf dnselben Wert, weshalb ich mal davon ausgehe, dass dieses " & 0xffffffff" etwas in einen unsigned long umwandelt.
Doch wie komme ich unter python 3 nun auf eine "signed int"?
crc-32 signed int mit python 3?
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
Ich bekomme eine checksum und muss diese mit meiner selbstgebildeten checksum vergleichen.__deets__ hat geschrieben:Das ist ja immer noch eine 32-bit-checksumme. Nur der Datentyp in Python, der die dann am Ende aufnimmt, ist halt ein long. Wie willst du das denn weiterverarbeiten?
Den "checkstring" dafür muss ich selbst bilden, könnte also theoretisch schon dort der fehler stecken.
Ich bekomme nämlich zb als Vorgabe:
-2066223162
Während meine Berechnug dies ausspuckt:
2228744134
Und auf Nachfrage warum meine checksum falsch ist, bekam ich die Antwort:
Leider wurde bisher nicht weiter darauf eingegangen, weshalb ich nun hier nachgefragt habe.checksum is a signed int
you're calculating it as an unsigned long
Mich verwundert aber auch, dass die vorgegebene checksum negativ ist. Gibts das?
Ich werde nochmal überprüfen, ob mein checkstring selbst richtig ist...
PS:
Nur nochmal zum Verständnis:
unsigned long und signed int sind vom wert her identisch, es muss also an meinem checkstring liegen?
Da die CRC auf einem *signed* int stattfindet, klar gibt's da negative checksummen.
Ich bekomme das konvertiert mit struct:
Insofern stimmt deine Berechnung, du musst nur tatsaechlich das Vorzeichen reparieren. Das hab' ich dir ja jetzt gezeigt
Ich bekomme das konvertiert mit struct:
Code: Alles auswählen
>>> v = 2228744134
>>> struct.pack("I", v)
b'\xc6\xef\xd7\x84'
>>> struct.unpack("i", struct.pack("I", v))
(-2066223162,)
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
ah vielen dank
In einer Zeile vom checkstring zur checksum also:
mychecksum = struct.unpack("i", struct.pack("I", binascii.crc32(checkstring.encode())))[0]
funktioniert
Allein oder auch mit Google wäre ich da nie drauf gekommen... =/
In einer Zeile vom checkstring zur checksum also:
mychecksum = struct.unpack("i", struct.pack("I", binascii.crc32(checkstring.encode())))[0]
funktioniert
Allein oder auch mit Google wäre ich da nie drauf gekommen... =/
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
__deets__ hat geschrieben:Ja, da stecken schon ein paar fortgeschrittene Grundlagen drin. Da hilft man auch gerne mit aus
der checkstring besteht aus zahlen, welche ich aus einer Liste beziehe, die ich im json format erhalten habe.
Also wenn ich es printe, sieht die Liste zb so aus: [1, 1.234, 0.23, 0.0002348]
Der checkstring wird dann über
":".join(liste)
gebildet.
Nun ist das Problem, dass "join" einen string will und keine Zahl.
Deswegen hab ich vorher jede Zahl der Liste vorher mit "str()" in einen string umgewandelt.
Nun gibt es dabei aber das Problem, dass eine Zahl wie 0.0000x in die "e-5" schreibweise umgewandelt wird, wodurch die checksum aber natürlich falsch wird.
Ich hatte das e-5 Problem schonmal und hatte als Lösung das hier verwendet:
'%.8f' % zahl
Doch in diesem Fall funktioniert das natürlich nicht, weil "0.0000x00" als string etwas anderes ist als "0.0000x". Wieviele Nachkommastellen die Zahl jeweils hat, kann ich nicht im voraus sagen, nur dass es maximal 8 sind.
Also wie packe ich diese Zahlen nun in einen checkstring?
Auch da hilf struct. Schau mal nach den float-Formaten. Du musst das entsprechend umwandeln. Ich kann mir nicht vorstellen, dass du da auf eine formatierte Zahldarstellung rausmusst. Würde ich zumindest denjenigen welchen um die Ohren hauen. Oder du musst den originalen JSON String nehmen. Was ich auch wieder um die Ohren hauen würde
-
- User
- Beiträge: 53
- Registriert: Freitag 7. Juli 2017, 12:35
danke__deets__ hat geschrieben:Auch da hilf struct. Schau mal nach den float-Formaten. Du musst das entsprechend umwandeln. Ich kann mir nicht vorstellen, dass du da auf eine formatierte Zahldarstellung rausmusst. Würde ich zumindest denjenigen welchen um die Ohren hauen. Oder du musst den originalen JSON String nehmen. Was ich auch wieder um die Ohren hauen würde
bei googlen nach dem Problem stößt man meistens auf diese % f Lösung.
Habe jetzt aber eine Lösung gefunden, welche scheinbar prüft wieviele nachkommastellen gebraucht werden:
https://stackoverflow.com/questions/388 ... 1#38847691
Das funktioniert und werde ich dann für alle Zahlen anwenden, die kleiner als 0.0001 sind
Ich halte das für die falsche Herangehensweise, weil du dich damit darauf verlässt, das du und der JSON Encoder die gleiche Zahldastellung haben. Und zwar *alle* JSON Encoder. Die Sender Seite hat ja auch einen. Ob das garantiert ist, das solltest du zumindest überprüfen. Oder zb den JSON Encoder benutzten.
@Scholastik: crc-Checksummen werden über Bits gebildet, es gibt also soetwas wie Vorzeichen nicht, das ist nur eine Darstellung. Das sinnvolle Vorgehen ist also die Checksummen vor dem Vergleich auf 32bit zu beschneiden:
Zweiter Punkt: es gibt keine eindeutige Dezimaldarstellung für Fließkommazahlen. Diese für eine Checksumme zu benutzen ist also von vornherein zum Scheitern verurteilt. Wer kommt auf solch eine Idee? Woher kommen diese Zahlen? Wer bildet die Checksumme? Wie kann man das ändern?
Code: Alles auswählen
checksumme1 = 2228744134
checksumme2 = -2066223162
if (checksumme1-checksumme2) & 0xffffffff == 0:
print("identisch")