Seite 1 von 1

mit Bitmasken arbeiten

Verfasst: Mittwoch 21. Februar 2007, 18:34
von Jay-Pi
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

Verfasst: Mittwoch 21. Februar 2007, 18:57
von Jay-Pi
: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

Verfasst: Mittwoch 21. Februar 2007, 20:55
von EyDu
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

Verfasst: Mittwoch 21. Februar 2007, 21:20
von Jay-Pi
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 :!:

Verfasst: Samstag 24. Februar 2007, 12:09
von Dill
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)

Verfasst: Montag 26. Februar 2007, 10:23
von Jay-Pi
:?
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

Verfasst: Montag 26. Februar 2007, 11:47
von 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.

Verfasst: Dienstag 27. Februar 2007, 17:14
von Dill
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())


Re: mit Bitmasken arbeiten

Verfasst: Donnerstag 1. März 2007, 23:17
von Joghurt
Ü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