私はpythonでバイナリファイルを読んでおり、ファイル形式のドキュメントはこう言っています:
フラグ(バイナリ)意味
1 nnn nnnn続くnnn nnnn(最大127回)のデータバイトが続くことを示します。
0 nnn nnnn nnn nnnnバイトの画像データ(最大127バイト)があり、重複がないことを示します。
n 000 0000行末フィールド。行レコードの終わりを示します。 nの値は0または1のいずれかです。行末フィールドは必須であり、上記の行レコードフィールドの長さに反映されることに注意してください。
ファイルを読み取るとき、私は1 nnn nnnn
を返すバイトを期待しています。ここで、nnn nnnn
の部分は50でなければなりません。
私はこれを以下を使用して行うことができました:
flag = byte >> 7
numbytes = int(bin(byte)[3:], 2)
しかし、numbytesの計算は安価な回避策のように感じられます。
Numbytesの計算を実行するために、より多くのビット計算を実行できますか?
これにどのように取り組みますか?
ファイルのバイトとAND演算されたマスクを使用して、先頭ビットを取り除くことができます。残りのビットの値が残ります。
mask = 0b01111111
byte_from_file = 0b10101010
value = mask & byte_from_file
print bin(value)
>> 0b101010
print value
>> 42
ビットマスキングを行う場合、2進数は16進数よりも理解しやすいと思います。
編集:あなたのユースケースのもう少し完全な例:
LEADING_BIT_MASK = 0b10000000
VALUE_MASK = 0b01111111
values = [0b10101010, 0b01010101, 0b0000000, 0b10000000]
for v in values:
value = v & VALUE_MASK
has_leading_bit = v & LEADING_BIT_MASK
if value == 0:
print "EOL"
Elif has_leading_bit:
print "leading one", value
Elif not has_leading_bit:
print "leading zero", value
ビットが設定されているかどうかを確認する古典的なアプローチは、バイナリの「and」演算子を使用することです。
x = 10 # 1010 in binary
if x & 0b10: # explicitly: x & 0b0010 != 0
print('First bit is set')
N ^番目のビットが設定されているかどうかを確認するには、2の累乗、またはより良いビットシフトを使用します。
def is_set(x, n):
return x & 2 ** n != 0
# a more bitwise- and performance-friendly version:
return x & 1 << n != 0
is_set(10, 1) # 1 i.e. first bit - as the count starts at 0-th bit
>>> True
説明を正しく読んだ場合:
if (byte & 0x80) != 0:
num_bytes = byte & 0x7F
あなたはこのようにそれを行うことができます:
def GetVal(b):
# mask off the most significant bit, see if it's set
flag = b & 0x80 == 0x80
# then look at the lower 7 bits in the byte.
count = b & 0x7f
# return a Tuple indicating the state of the high bit, and the
# remaining integer value without the high bit.
return (flag, count)
>>> testVal = 50 + 0x80
>>> GetVal(testVal)
(True, 50)
そこに行きます:
class ControlWord(object):
"""Helper class to deal with control words.
Bit setting and checking methods are implemented.
"""
def __init__(self, value = 0):
self.value = int(value)
def set_bit(self, bit):
self.value |= bit
def check_bit(self, bit):
return self.value & bit != 0
def clear_bit(self, bit):
self.value &= ~bit
Int(bin(byte)[3:]、2)の代わりに、単に次のように使用できます:int(bin(byte >> 1)、2)
私があなたを正しく手に入れたかどうかはわかりませんが、私がそうした場合、これでうまくいくはずです:
>>> x = 154 #just an example
>>> flag = x >> 1
>>> flag
1
>>> nb = x & 127
>>> nb
26