在Python位掩码 [英] Bit masking in Python

查看:848
本文介绍了在Python位掩码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有个字节(从其他供应商),其中的潜在位掩码如下:

值1 = 0×01
值2 = 0×02
值3 = 0×03
值4 = 0×04
值5 = 0×05
value6 = 0×06
value7 = 0X40
value8 = 0x80的

我可以通过value6是present上值1的罪名。然后value7可以或可以不被设置。 value8可以或可以不被设置。

因此​​,这是合法的:VALUE2 | value7 | value8
这是不合法的:数值|值3 | value7

我要弄清楚值7是否设置,value8设置,什么剩余价值。

我有以下的蟒蛇code。有没有更优雅的方式来做到这一点?

 值1 = 0×01
值2 = 0×02
值3 = 0×03
值4 = 0×04
值5 = 0×05
value6 = 0×06
value7 = 0X40
value8 = 0x80的高清format_byte_as_bits(值):
    返回格式(价值,'B')。zfill(8)高清mask_bits_on_byte(字节,掩模):
    inverse_of_mask = ^面膜0b11111111
    返回字节和放大器; inverse_of_mask高清parse_byte(字节):    value7_set =字节和放大器; value7 == value7
    value8_set =字节和放大器; value8 == value8
    字节= mask_bits_on_byte(字节,value7)
    字节= mask_bits_on_byte(字节,value8)
    BASE_VALUE =字节
    返回value7_set,value8_set,BASE_VALUE#示例1
字节=值3 | value7
value7_set,value8_set,BASE_VALUE = parse_byte(字节)
打印(BASE_VALUE =+ STR(BASE_VALUE))
打印(value7_set =+ STR(value7_set))
打印(value8_set =+ STR(value8_set))
打印()#输出:
#BASE_VALUE = 3
#value7_set = TRUE
#value8_set =假#示例2
字节=值5
value7_set,value8_set,BASE_VALUE = parse_byte(字节)
打印(BASE_VALUE =+ STR(BASE_VALUE))
打印(value7_set =+ STR(value7_set))
打印(value8_set =+ STR(value8_set))
打印()#输出:
#BASE_VALUE = 5
#value7_set =假
#value8_set =假#示例3
字节=值| value7 | value8
value7_set,value8_set,BASE_VALUE = parse_byte(字节)
打印(BASE_VALUE =+ STR(BASE_VALUE))
打印(value7_set =+ STR(value7_set))
打印(value8_set =+ STR(value8_set))#输出:
#BASE_VALUE = 1
#value7_set = TRUE
#value8_set = TRUE

编辑 - 我爱计算器。因此,许多有用的答案,这么快!你们是真棒!希望我可以标记所有的答案。但我会至少给大家一个上一票!

EDIT2 - 基于下面的答案中,code简化为以下内容:

 值1 = 0×01
值2 = 0×02
值3 = 0×03
值4 = 0×04
值5 = 0×05
value6 = 0×06
value7 = 0X40
value8 = 0x80的高清parse_byte(字节):
    返回字节和放大器; value7,字节和放大器; 0x80的,字节和放大器; 7#示例1
字节=值3 | value7
value7_set,value8_set,BASE_VALUE = parse_byte(字节)
打印(BASE_VALUE =+ STR(BASE_VALUE))
如果value7_set:打印(value7_set)
如果value8_set:打印(value8_set)
打印()#示例2
字节=值5
value7_set,value8_set,BASE_VALUE = parse_byte(字节)
打印(BASE_VALUE =+ STR(BASE_VALUE))
如果value7_set:打印(value7_set)
如果value8_set:打印(value8_set)
打印()#示例3
字节=值| value7 | value8
value7_set,value8_set,BASE_VALUE = parse_byte(字节)
打印(BASE_VALUE =+ STR(BASE_VALUE))
如果value7_set:打印(value7_set)
如果value8_set:打印(value8_set)
打印()


解决方案

你的大部分值* 常量实际上并没有位掩码,只有 value7 value8 是。我定义另一个位掩码来提取低位,所以我会在共有三个位掩码:

  = MASK0 0x07执行
掩码1 = 0X40
MASK2 = 0x80的

现在您的功能变得

 高清parse_byte(字节):
    返回字节和放大器; MASK2,字节和放大器;掩码1,字节和放大器; MASK0

我没有转换结果布尔 - 我不明白为什么这应该是必要的。当检查与如果返回的值,它会被隐式转换为布尔反正。

还要注意的是

 格式(价值,'B')。zfill(8)

可以简化为

 格式(价值08B)

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

解决方案

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

这篇关于在Python位掩码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆