1byteデータに含まれる任意のbit位置にある値を取得する方法

1 min read読了の目安(約1400字

やりたいこと

1byteデータから任意のbit位置にある値を取得する方法をいろいろ考えたので記事に残したいと思います。

例えば0b10100000という1byteのデータがあったとき(以下図)、4bit目から2bit分の値である0b10)を取得する方法です。

今回思いついた方法が以下の2点です。

  1. 文字列に変換
  2. bit演算を利用

ソースコードはpythonです。

文字列に変換

目的のbit値を文字列に変換し、bit位置=文字列の位置と考えて目的のbit値を抽出するやり方です。

この方法の注意点は文字列の位置とbit位置は方向が逆である点です。以下の例では、文字列を反転([::-1])させてから目的の値を抽出し、抽出後に再反転させて、正しいbit値に変換しています。

bit_pos = 4
bit_len = 2
value = 0xA0 # 0b10100000

# bit値として文字列に変換
bit_str = "{:08b}".format(value)
# bit_str = '10100000'

# 文字列を反転し、bit位置(`bit_pos`)とbit長(`bit_len`)で目的の値を抽出。抽出値はbit値としては反転しているので、再反転して値を戻す
value = bit_str[::-1][bit_pos:bit_pos+bit_len][::-1]
result = int(value, 2)
# result: 2 (='0b10')

bit_pos, bit_lenをうまく文字列位置に変換できれば、文字列反転をさせずに目的の値が抽出できそうですね。

bit演算を使う

次は、bit演算を使う方法です。具体的にはbitシフト演算論理積を利用します。

まず、対象データの取得したいbit位置が0bitになるよう右シフトします。
これに対して、00000011という値と論理積を計算してあげれば、目的のbit値を取得することができます。
なので 11111111=0xFFを右シフト して、論理積の対象データである00000011を作ります。

以上の処理を図でまとめると、以下のようになります。

実際のコードは以下の通りです。

bit_pos = 4
bit_len = 2
value = 0xA0 # 0b10100000
result = (value >> bit_pos) & (0xFF >> (8 - bit_len))
# result: 2 (='0b10')

終わりに

もっとシンプルでスマートに計算できそうな気がするのですが、これ以上の案は思いつきませんでした。
ただ、目的の値はこれで取得できそうです。

もっとbit操作をうまく使えるように、日々精進していきたいです。