Seite 1 von 1

aus binärdaten signed long machen (ohne struct)

Verfasst: Samstag 29. November 2008, 02:12
von szallah
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?

Verfasst: Samstag 29. November 2008, 08:33
von numerix
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

Verfasst: Samstag 29. November 2008, 09:06
von 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