2009-06-10 8 views
3

Ich verwende pySerial, um Daten von einem angeschlossenen Gerät einzulesen. Ich möchte die Prüfsumme jedes empfangenen Pakets berechnen. Das Paket wird als Char-Array eingelesen, wobei die tatsächliche Prüfsumme das letzte Byte am Ende des Pakets ist. Um die Prüfsumme zu berechnen, würde ich normalerweise die Paketnutzlast summieren und dann mit der tatsächlichen Prüfsumme vergleichen.Gibt es eine Möglichkeit, zwei Bytes mit Überlauf in Python hinzuzufügen?

Normalerweise würden wir in einer Sprache wie C einen Überlauf erwarten, weil die Prüfsumme selbst nur ein Byte ist. Ich bin mir nicht sicher über die Interna von Python, aber aus meiner Erfahrung mit der Sprache sieht es so aus, als würde es auf eine größere Variable (vielleicht eine interne bigInt-Klasse oder etwas) voreingestellt. Gibt es überhaupt etwas, um das erwartete Verhalten des Hinzufügens von zwei Zeichen nachzuahmen, ohne meine eigene Implementierung zu schreiben? Vielen Dank.

Antwort

6

Sicher, nehmen Sie einfach den Modul Ihres Ergebnisses, um es wieder in der gewünschten Größe anzupassen. Sie können den Modul am Ende oder bei jedem Schritt ausführen. Zum Beispiel:

>>> payload = [100, 101, 102, 103, 104] # arbitrary sequence of bytes 
>>> sum(payload) % 256 # modulo 256 to make the answer fit in a single byte 
254 # this would be your checksum 
+3

Nizza einfaches Beispiel. Beachten Sie, dass eine andere gebräuchliche Methode zum Abschneiden auf ein Byte bitweise UND mit 0xFF ist, also "sum (Nutzlast) & 0xFF". –

+0

@benhoyt sieht aus, als ob wir das gleiche denken ;-) – nategood

2

um das frühere Beispiel zu verbessern, nur bitweise - und es mit 0xFF. nicht sicher, ob Python die Optimierung standardmäßig ausführt oder nicht.

sum(bytes) & 0xFF 
+0

Ich bin mir nicht sicher, was Python unter der Haube tut, aber ein schneller Test zeigt an, dass beide Methoden fast die gleiche Zeit benötigen. Die Summe wird auf jeden Fall der Hauptteil der Arbeit sein. – Kiv

+0

Die meisten anständigen optimierenden Compiler machen eine Verringerung der Stärke und implementieren Sie Ihre "% (2^n)" als "& ((1 << n) -1)". Wäre für den Python-Interpreter nicht zu schwer, das Gleiche zu tun. –

+0

Betrachtet man die Ausgabe von "dis.dis (Lambda x: x% 256)", sieht es so aus, als ob diese Optimierung nicht angewendet wird. Der kleine Unterschied in der Laufzeit ist wahrscheinlich auf die Tatsache zurückzuführen, dass die tatsächliche und/mod-Operation ein sehr kleiner Teil der Gesamtkosten ist. – Brian

0

Summieren den Bytes und dann den Modul nimmt, wie in sum(bytes) % 256 (oder sum(bytes) & 0xFF), ist (in vielen Programmiersprachen) anfällig auf ganzzahlige Überlauf, da es ein begrenzter maximaler Wert ist, die Integer-Typen darstellen.

Aber, da wir über Python sprechen, ist dies technisch kein Problem: Python-Ganzzahlen sind arbitrary-precision, so dass ein Integer-Überlauf nicht auftreten kann.

Wenn Sie das Modul-Operation an einem Element-für-Element-Basis durchführen möchten, können Sie functools.reduce() verwenden:

>>> payload = [100, 101, 102, 103, 104] # arbitrary sequence of bytes 
# (Python 3 uses functools.reduce() instead of builtin reduce() function) 
>>> import functools 
>>> functools.reduce(lambda x,y: (x+y)%256, payload) 
254