mit Bitmasken arbeiten

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
Jay-Pi
User
Beiträge: 19
Registriert: Dienstag 13. Februar 2007, 14:10

Hallo,

kann mir jemand helfen bei dem Thema Bits und Bytes und Masken?

Folgende Problemstellung:

ich einen Speicherplatz mit 2 Bytes (die ersten 14 Bits werden verwendet) und möchte Bit 7-13 auslesen. Habe sogar die Masken dafür, kenne mich allerdings nicht so im Gebrauch mit diesen aus.

2 Byte
Bit 6-0 Maske 007F (Hex)
Bit 13-7 Maske 3F80 (Hex)

Beide Stellen beinhaltet einen Index/Zahl, welche zwischen 0 und 82 liegen sollte bzw vielleicht den Wert 32767.

Bekomme aber immer Werte im Bereich von mehreren Tausend oder Millionen.

Code: Alles auswählen

#test:  0x40 0x05
test, = unpack("<H", test)   => 1344
test & 0x007F   => 64
test & 0x3F80   => 1280
Das zweite müsste meiner Meinung nach aber 10 ergeben (Durch testen erwartet)

Habe mir das auch schon mit nullen und einsen aufgemalt:

Teil 1 | Teil2 | frei
0000000|0000000| ??

Im Besipiel vermute ich:
1000000|101??????

Masken dazu
1111111 (007F h und 127 d)
11111110000000 (3F80 h und 16256)

Wenn ich mir das hier so angucke verstehe ich noch weniger :-)

Ich brauche nur einen Schubs im verwenden von Masken, Bitweiser Addition oder war das binär? oder lesen von Binär- Hexadezimal- und Dezimalzahlen.

Gruss
JP
Jay-Pi
User
Beiträge: 19
Registriert: Dienstag 13. Februar 2007, 14:10

:D
Yepeee

ich habs. Da fehlt noch ein Schifting (>>)

Wieder was dazugelernt.

Erst die Maske anwenden und dann den Rest "wegkürzen".
Habe es zwar noch nicht mit Bits in der Mitte probiert, aber das reicht mir erstmal so:

Code: Alles auswählen

wert_mit_maske = test & 0x3F80   => 1280
finaler_inhalt = test >> 7  => 10
Was habe ich getan?
Ich habe das ganze um 7 Bits nach rechts geschiftet und bekomme den Rest ab der 8. Position.
Mit den Begrifflichkeiten Rechts und Links muss ich noch klar kommen, aber gemeint ist wahrscheinlich ein Zeiger oder sowas.

Gruss
JP
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Nee, da ist kein Zeiger gemeint :D

Da ich als Informatiker mindestens genau so faul bin wie Mathematiker hier ein Link der alles erklären sollte:

http://en.wikipedia.org/wiki/Bitwise_operation
Jay-Pi
User
Beiträge: 19
Registriert: Dienstag 13. Februar 2007, 14:10

Ach herje,

da gibt es ja logisches, arythmetisches und rotierendes Verschieben.

Das sind für heute zu viele Nullen und Einsen.

Der Artikel ist aber sehr hilfreich danke :!:
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

hilfreich ist da auch:

http://aspn.activestate.com/ASPN/Cookbo ... ipe/113799

Code: Alles auswählen

#
# bitfield manipulation
#

class bf(object):
    def __init__(self,value=0):
        self._d = value

    def __getitem__(self, index):
        return (self._d >> index) & 1 

    def __setitem__(self,index,value):
        value    = (value&1L)<<index
        mask     = (1L)<<index
        self._d  = (self._d & ~mask) | value

    def __getslice__(self, start, end):
        mask = 2L**(end - start) -1
        return (self._d >> start) & mask

    def __setslice__(self, start, end, value):
        mask = 2L**(end - start) -1
        value = (value & mask) << start
        mask = mask << start
        self._d = (self._d & ~mask) | value
        return (self._d >> start) & mask

    def __int__(self):
        return self._d

k = bf()
k[3:7]=5
print k[3]
print k[5]
k[7]=1
print k[4:8]
print int(k)
Jay-Pi
User
Beiträge: 19
Registriert: Dienstag 13. Februar 2007, 14:10

:?
Keine Ahnung was das Ding macht, aber wie benutze ich das denn?

Ich habe sowas wie

Code: Alles auswählen

komplett = 8384 # Mit der Länge von 2 Byte, bzw 14 Bit, weil Rest leer

# also folgendes?

k = bf()
k[0:16] = komplett

# Ich benötige den Wert an Position 7-13
# normalerweise würd ich jetzt sowas machen,
# wie funktioniert das mit der Klasse?

teil = (komplett & 0x3F80) >> 7
print teil # müsste 65 sein
Gruss
JP
BlackJack

So:

Code: Alles auswählen

def main():
    bits = BitField(8384)
    print bits[7:14]
Die Indexe bei Slices stellt man sich am besten nicht als Indexe *auf* die Elemente sondern *zwischen* die Elemente vor. 0 ist vor dem ersten Element, 1 ist zwischen dem ersten und zweiten und so weiter. Also ist 7 vor Bit Nr. 7 (das 8. Element weil die Zählung bei 0 beginnt) und 13 wäre vor Bit Nr. 13. Da das aber mit erfasst werden soll, muss hier eine 14 zum "ausschneiden" angegeben werden.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

Ich habe diese klasse noch etwas erweitert.
Evtl ist ja was dabei für dich.
(achtung: habe auch funktionalität entfernt!)

noch eine frage:
Wie kann ich den xor - operator dazu bringen mit der Bitfieldklasse zu arbeiten? siehe methode diff()

Code: Alles auswählen

class Bitfield(object):
    def __init__(self,value=0):
        self._d = value
        
    def __int__( self ):
        return _d
    
    def __getitem__(self, index):
        return (self._d >> index) & 1 
    
    def __setitem__(self,index,value):
        value    = (value&1)<<index
        mask     = (1)<<index
        self._d  = (self._d & ~mask) | value
    
    def __getslice__(self, start, end):
        raise Exception("NOT SUPPORTED")
    
    def __setslice__(self, start, end, value):
        raise Exception("NOT SUPPORTED")
    
    #Listendarstellung
    def to_list(self):
        lst = [(self._d >> i) & 1  for i in range(16)]
        lst.reverse()
        return lst
    
    #Liste der gesetzten Bits
    def active_list(self):
        return [i for i in range(16) if ((self._d >> i) & 1) == 1]
    
    #XOR ... kann man eigentlich den ^ operator beibringen 
    #mit der Klasse Bitfield zu arbeiten?
    def diff(self, bitfield):
        return bf(self._d^int(bitfield))
    
    #einzelnes Bit setzen
    def set_active(self, index):
        self.__setitem__(index, 1)
    
    #einzelnes Bit löschen
    def set_inactive(self, index):
        self.__setitem__(index, 0)
        
    def __str__(self):
        return str(self.to_list())

Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Übrigens... Der Vorteil vom Hexadezimalsystem (und der Grund, warum es überhaupt benutzt wird) ist der, das jede "Ziffer" genau 4 Bit lang ist.

Ergo:

Code: Alles auswählen

0011 1111 1000 0000
  3    F    8    0    h
Antworten