2011-12-14 13 views
5

mam bajt (od innego producenta), w których potencjalne maski bitowe są następujące:bitów maskowania Pythona

wartosc1 = 0x01 wartość2 = 0x02 wartość3 = 0x03 value4 = 0x04 value5 = 0x05 wartość6 = 0x06 wartość7 = 0x40 wartość8 = 0x80

Mogę liczyć na JEDEN z wartości1 do wartości6 obecnych. A następnie wartość7 może lub nie może być ustawiona. wartość 8 może lub nie może być ustawiona.

To jest legalne: wartość2 | wartość7 | value8 To nie jest legalne: wartość1 | wartość3 | value7

Muszę dowiedzieć się, czy ustawiono wartość 7, ustawiono wartość 8 i jaka jest pozostała wartość.

Mam następujący kod Pythona. Czy istnieje bardziej elegancki sposób na zrobienie tego?

value1 = 0x01 
value2 = 0x02 
value3 = 0x03 
value4 = 0x04 
value5 = 0x05 
value6 = 0x06 
value7 = 0x40 
value8 = 0x80 

def format_byte_as_bits(value): 
    return format(value,'b').zfill(8) 

def mask_bits_on_byte(byte,mask): 
    inverse_of_mask = mask^0b11111111 
    return byte & inverse_of_mask 

def parse_byte(byte): 

    value7_set = byte & value7 == value7 
    value8_set = byte & value8 == value8 
    byte = mask_bits_on_byte(byte,value7) 
    byte = mask_bits_on_byte(byte,value8) 
    base_value = byte 
    return value7_set,value8_set,base_value 

# Example 1 
byte = value3 | value7 
value7_set,value8_set,base_value = parse_byte(byte) 
print("base_value = "+str(base_value)) 
print("value7_set = "+str(value7_set)) 
print("value8_set = "+str(value8_set)) 
print() 

# Output: 
# base_value = 3 
# value7_set = True 
# value8_set = False 

# Example 2 
byte = value5 
value7_set,value8_set,base_value = parse_byte(byte) 
print("base_value = "+str(base_value)) 
print("value7_set = "+str(value7_set)) 
print("value8_set = "+str(value8_set)) 
print() 

# Output: 
# base_value = 5 
# value7_set = False 
# value8_set = False 

# Example 3 
byte = value1 | value7 | value8 
value7_set,value8_set,base_value = parse_byte(byte) 
print("base_value = "+str(base_value)) 
print("value7_set = "+str(value7_set)) 
print("value8_set = "+str(value8_set)) 

# Output: 
# base_value = 1 
# value7_set = True 
# value8_set = True 

EDYCJA - I LOVE stackoverflow. Tak wiele przydatnych odpowiedzi, tak szybko! Jesteście niesamowici! Chciałbym zaznaczyć wszystkie odpowiedzi. Ale przynajmniej dam wszystkim głos w górę!

EDIT2 - Na podstawie poniższych odpowiedzi, kod jest uproszczone do następującego:

value1 = 0x01 
value2 = 0x02 
value3 = 0x03 
value4 = 0x04 
value5 = 0x05 
value6 = 0x06 
value7 = 0x40 
value8 = 0x80 

def parse_byte(byte): 
    return byte & value7, byte & 0x80, byte & 7 

# Example 1 
byte = value3 | value7 
value7_set,value8_set,base_value = parse_byte(byte) 
print("base_value = "+str(base_value)) 
if value7_set: print("value7_set") 
if value8_set: print("value8_set") 
print() 

# Example 2 
byte = value5 
value7_set,value8_set,base_value = parse_byte(byte) 
print("base_value = "+str(base_value)) 
if value7_set: print("value7_set") 
if value8_set: print("value8_set") 
print() 

# Example 3 
byte = value1 | value7 | value8 
value7_set,value8_set,base_value = parse_byte(byte) 
print("base_value = "+str(base_value)) 
if value7_set: print("value7_set") 
if value8_set: print("value8_set") 
print() 

Odpowiedz

10

Większość twoich value* stałych nie są faktycznie bit maski, tylko value7 i value8 są. Chciałbym określić inną maskę bitową aby wyodrębnić mniejsze kawałki, więc chciałbym mieć trzy bitowych masek w sumie:

mask0 = 0x07 
mask1 = 0x40 
mask2 = 0x80 

Teraz czynność staje

def parse_byte(byte): 
    return byte & mask2, byte & mask1, byte & mask0 

Nie przekonwertować wyniki do bool - - Nie rozumiem, dlaczego to powinno być konieczne. Podczas sprawdzania zwróconej wartości za pomocą if, mimo to zostanie ona niejawnie przekonwertowana na bool.

Należy również pamiętać, że

format(value,'b').zfill(8) 

można uprościć do

format(value,'08b') 
+0

Bardzo zwięzłe i doceniam również wskazówkę na temat zfill. Używam formatu (wartość, "b"). Zfill (8) wszędzie, teraz mogę po prostu użyć formatu (wartość, "08b"). Dzięki za twoją odpowiedź! –

+1

Na marginesie, prostym sposobem tworzenia poprawnych bitmask z ładnym czytelnym kodem jest zapisanie ich w stylu 'value1 = 1 << 0',' value2 = 1 << 1' (etc). To znaczy, weź jeden kawałek i po prostu zmień przesunięcie. Błędy są bardziej oczywiste niż w przypadku liter heksadecymalnych lub dziesiętnych. Jeśli maska ​​wymaga zestawu wielu bitów, po prostu '|' te razem (np. 'Wartość3 = (1 << 2) | (1 << 3)' zamiast 'wartość3 = 0x0c'). – Kat

3

Nie trzeba dwie inne funkcje:

def parse_byte(byte): 
    value7_set = byte & value7 == value7 
    value8_set = byte & value8 == value8 
    base_value = byte & 7 
    return value7_set,value8_set,base_value 
+0

Dziękujemy! Nie pomyślałem o bajcie i 7. –

1

To trochę rozwlekły, ale doskonale w porządku. Jedyną zmianą, że zrobię to, aby uprościć parse_byte:

def parse_byte(byte): 

    value7_set = byte & value7 == value7 
    value8_set = byte & value8 == value8 
    base_value = mask_bits_on_byte(byte,value7 | value8) 
    return value7_set,value8_set,base_value 
+0

Dziękuję za odpowiedź! –

4

Biorąc pod uwagę wartość takich jak:

>>> x = 0b10001000 

można dowiedzieć się, czy górne bity ustawione są w:

>>> bit8 = bool(x & 0b10000000) 
>>> bit7 = bool(x & 0b01000000) 

Aby dowiedzieć się, jakie niższy bit jest ustawiony, należy użyć słownika:

>>> bdict = dict((1<<i, i+1) for i in range(6)) 
>>> bdict[x & 0b00111111] 
4 
+0

Dzięki za odpowiedź! –

+0

@MatthewLund Z przyjemnością pomogę :-) –

Powiązane problemy