1. ホーム
  2. python

[解決済み] Pythonでビットマスキング

2022-03-04 08:39:57

質問

私は、潜在的なビットマスクが以下のようなバイト(いくつかの他のベンダーのもの)を持っています。

値1 = 0x01 値2 = 0x02 値3 = 0x03 値4 = 0x04 値5 = 0x05 値6 = 0x06 値7 = 0x40 値8 = 0x80

値1から値6までのうち、1つだけ存在することを数えることができる。 そして、value7が設定されているかどうか。value8が設定されているかどうか。

つまり、これは合法です:値2|値7|値8 これは合法ではありません:値1|値3|値7

値7が設定されているのか、値8が設定されているのか、残りの値は何なのかを把握する必要がありますね。

私は以下のようなpythonのコードを持っています。 これを行うには、よりエレガントな方法があるのでしょうか?

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 - 私はstackoverflowが大好きです。 たくさんの有用な回答が、こんなに早く! あなたたちは最高です! すべての答えに印をつけられたらいいんだけど。 でも、少なくともみんなにアップボートを贈ります!

EDIT2 - 以下の回答をもとに、コードを以下のように簡略化しました。

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

解決方法は?

ほとんどの value* の定数は、実際にはビットマスクではなく value7value8 があります。 下位ビットを抽出するために別のビットマスクを定義するので、合計3つのビットマスクがあることになりますね。

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

この関数は次のようになります。

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

への変換はしていません。 bool -- なぜこれが必要なのかわかりません。 で返された値をチェックすると if に暗黙のうちに変換されます。 bool というように、とにかく

また、次のことにも注意してください。

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

は、次のように簡略化できます。

format(value,'08b')