aus binärdaten signed long machen (ohne struct)

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
szallah
User
Beiträge: 14
Registriert: Dienstag 27. Mai 2008, 07:31

hi...
seit nem monat suche ich nach ner lösung für mein problem und finde einfach keins. wohlmöglich deshalb, weil ich garnicht genau weiß nach was ich googeln könnte um mein problem zu präzisieren. zumindest haben meine recherchen nur dazu geführt, dass python "einfach so" hex-werte anders versteht als ich das gerne hätte...

worum es geht:
es wird ne anfrage an einen server geschickt, und der liefert einem ne binäre antwort. ein teil dieser antwort enthält eine zahl, die sowohl positiv als auch negativ sein kann.
stark vereinfacht und direkt lauffähig sieht das ganze so aus:

Code: Alles auswählen

import binascii
from struct import *

hexstring = 'fb4391f8' # die - in diesem testfall - negative zahl
binary_string = binascii.a2b_hex(hexstring) # jetzt binary, weil so kommt's ja vom server

def so_gehts_theoretisch(data):
    return unpack('>L', data)[0] # L -> unsigned long, also doch nicht was ich brauche

def so_gehts_wirklich(data):
    return unpack('>l', data)[0] # l -> signed long, das will ich

def so_solls_gehen(data):
    return long(data.encode('hex'),16) # -> unsigned long, will aber signed long haben

print so_gehts_theoretisch(binary_string) # -> 4215509496
print so_gehts_wirklich(binary_string)    # -> -79457800
print so_solls_gehen(binary_string)       # -> 4215509496
mit struct funktioniert das ganze. da das programm aber am ende per PyS60 auf nem handy laufen soll und somit alles eher "kompakt" sein soll, will ich auf den import von struct verzichten. außerdem kann ich mir schlichtweg nicht vorstellen, dass python nicht in der lage ist aus den binären daten nen signed long zu machen. ich weiß halt nur nicht wie.

"interessant" ist ja, dass die dritte funktion durchaus funktioniert wenn eine positive zahl vom server geliefert wird (z.b. '029ba3fd')... nur mit negativen klappt's halt nicht mehr...

also, wie muss ich die dritte funktion abändern um die negative zahl zu bekommen?
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Probier das mal:

Code: Alles auswählen

def gehtso(binstr):
    value = int(binstr.encode('hex'),16)
    if value>=int("80000000",16):
        value = value - int("ffffffff",16) - 1
    return value
BlackJack

Wobei ich für den echten Einsatz doch das `struct`-Modul empfehlen würde. Das sieht nach einem Fall von "premature optimization" aus.

Edit: Und noch als Alternative das Ganze über Bitverknüpfungen:

Code: Alles auswählen

def this_works(data):
    result = int(data.encode('hex'), 16)
    if result & 2**31:
        result = -((result ^ (2**32 - 1)) + 1)
    return result
Antworten