Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bit masking in Python

I have a byte (from some other vendor) where the potential bit masks are as follows:

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

I can count on ONE of value1 through value6 being present. And then value7 may or may not be set. value8 may or may not be set.

So this is legal: value2 | value7 | value8 This is not legal: value1 | value3 | value7

I need to figure out whether value 7 is set, value8 is set, and what the remaining value is.

I have the following python code. Is there a more elegant way to do this?

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

EDIT - I LOVE stackoverflow. So many useful answers, so quickly! You guys are awesome! Wish I could mark all the answers. But I'll at least give everyone an up vote!

EDIT2 - Based on the answers below, the code is simplified to the following:

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()
like image 411
Matthew Lund Avatar asked Dec 14 '11 17:12

Matthew Lund


People also ask

What is bit mask in Python?

Erle Robotics Learning Python GitBook Free A bit mask is just a variable that aids you with bitwise operations.

What is bit masking with example?

To represent a set of N items we need a sequence of N bits where every bit represents an item in the Set. This sequence of bits used to represent a subset of a set is usually referred to as a mask. For example, the sequence of bits 10101 is a mask used to represent a set of size 5.

What is the purpose of bit masking?

Bit masks are used to access specific bits in a byte of data. This is often useful as a method of iteration, for example when sending a byte of data serially out a single pin. In this example the pin needs to change its state from high to low for each bit in the byte to be transmitted.

What is masking in bit manipulation?

Masking is the act of applying a mask to a value. This is accomplished by doing: Bitwise ANDing in order to extract a subset of the bits in the value. Bitwise ORing in order to set a subset of the bits in the value. Bitwise XORing in order to toggle a subset of the bits in the value.


1 Answers

Most of your value* constants aren't actually bit masks, only value7 and value8 are. I'd define another bit mask to extract the lower bits, so I would have three bit masks in total:

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

Now your function becomes

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

I did not convert the results to bool -- I don't see why this should be necessary. When checking the returned value with if, it will be implicitly converted to bool anyway.

Also note that

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

can be simplified to

format(value,'08b')
like image 66
Sven Marnach Avatar answered Oct 16 '22 23:10

Sven Marnach