2011-12-14 12 views
5

ho un byte (da qualche altro fornitore) dove i potenziali maschere di bit sono i seguenti:mascheramento di bit in Python

value1 = 0x01 value2 = 0x02 value3 = 0x03 valore4 = 0x04 valore5 = 0x05 valore6 = 0x06 valore7 = 0x40 valore8 = 0x80

Posso contare su UNO di valore da 1 a valore 6 presente. E quindi value7 può o non può essere impostato. value8 può o non può essere impostato.

Quindi questo è legale: valore2 | valore7 | valore8 Questo non è legale: valore1 | valore3 | value7

Ho bisogno di capire se il valore 7 è impostato, il valore 8 è impostato e qual è il valore rimanente.

Ho il seguente codice Python. C'è un modo più elegante per farlo?

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 

MODIFICA - I LOVE stackoverflow. Così tante risposte utili, così in fretta! Voi ragazzi siete fantastici! Vorrei poter contrassegnare tutte le risposte. Ma darò almeno un voto a tutti!

EDIT2 - Sulla base delle risposte di seguito, il codice è semplificato al seguente:

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() 

risposta

10

maggior parte dei vostri value* costanti non sono in realtà bit maschere, solo value7 e value8 sono. Mi piacerebbe definire un altro maschera di bit per estrarre i bit inferiori, così avrei maschere di tre bit in totale:

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

Ora la funzione diventa

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

non ho convertire i risultati per bool - - Non vedo perché questo dovrebbe essere necessario. Quando si controlla il valore restituito con if, verrà convertito implicitamente in bool.

Si noti inoltre che

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

può essere semplificata

format(value,'08b') 
+0

Molto sintetico e apprezzo molto anche la punta sullo zfill. Uso il formato (valore, 'b'). Zfill (8) dappertutto, ora posso solo usare il formato (valore, '08b'). Grazie per la risposta! –

+1

Per inciso, un modo semplice per creare maschere di bit corrette con un buon codice leggibile è di scriverle come 'valore1 = 1 << 0',' valore2 = 1 << 1' (ecc.). Cioè, prendi un po 'e cambia semplicemente il turno. Gli errori sono più ovvi che con letterali esadecimali o decimali. Se la maschera ha bisogno di più bit impostati, solo '|' quelli insieme (ad esempio 'value3 = (1 << 2) | (1 << 3)' invece di 'value3 = 0x0c'). – Kat

3

Non è necessario le altre due funzioni:

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

Grazie! Non ho pensato al byte & 7. –

1

E 'un po' prolisso, ma perfettamente bene. L'unico cambiamento che vorrei fare è quello di semplificare 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

Grazie per la tua risposta! –

4

Dato un valore come ad esempio:

>>> x = 0b10001000 

È possibile scoprire se i bit superiori vengono impostati con:

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

per trovare quale po 'più basso è impostato, utilizzare un dizionario:

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

Grazie per la tua risposta! –

+0

@MatthewLund Felice di essere di aiuto :-) –

Problemi correlati