bytetobit

バイト列からビット列を取り出す方法を考えます。
文法はすべてC#を使用します。
バイト列とは、たとえば
byte[] x = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x9A}; // 16進数表示
として得られる配列x。
このバイト列の、a バイト目の b ビット目(左から数える)を始点として、n ビット取り出すという問題を考えます。
配列xを2進数で表すと、
{ 00010010, 00110100, 01010110, 01111000, 10011010 }
となります。
a,bは、0から数えるルールにしますので、
たとえば a=1, b=3, n=4 のとき、以下の下線部が選択されます。
{ 00010010, 00110100, 01010110, 01111000, 10011010 }

ここでは、n<=16の場合のみを考えます。

ケース1
b+n <= 8 のとき
x[a]の中で完結します。
まず、x[a]のビット0(これは左端のビット)から、ビットb-1までをすべてゼロにします。
  上の例では 00110100 → 00010100
  これはand演算(&)を使って行います。
次に、8-(b+n) の数だけ、右にシフトします。論理シフト(左端は常にゼロを補填する)。
  上の例では 00010100 → 8-(b+n) = 1ビットだけ右にシフト → 00001010
あとは、int型にでもキャストするなりして返してあげればよいです。


ケース2
8 < b+n <= 16のとき
例 a=1, b=5, n=9
{ 00010010, 00110100, 01010110, 01111000, 10011010 }
x[a]とx[a+1]のデータが必要になります。
   x[a]   = 00110100
   x[a+1] = 01010110
x[a]からは、n1 = 8-b ビット (=3)の情報を
x[a+1]からは、n2 = n-n1 ビット (=6)の情報を 提供します。
まず、x[a]のビット0からビットb-1までをゼロにします(and演算)。そしてn2ビット(=6)だけ左シフトします。
   x[a]  : 00110100 →(and演算) &u(){00000}100 → (左シフト) → 100000000 (9桁表示)これをy[a]とします。
次に、x[a+1]を 8-n2 ビット (=2)だけ右シフトします。
   x[a+1]: 01010110 → 00010101 これをy[a+1]とします。
最後に、y[a] | y[a+1]を計算
  00000001 0000000 | 00000000 00010101 = 00000001 00010101

C#プログラムで記載するとこうです。
               int n1 = 8 - b;
               int n2 = n - n1;
               int temp1 = (x[a] & mask[n1]) << n2;
               int temp2 = (x[a + 1] >> (16 - b - n));
               int result = temp1 | temp2;
なおmask配列の中身はこうです。
       byte[] mask = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };



ケース3
16 < b+n <= 24のとき
この場合は、3バイト分の情報から、上下をカットします。
C#プログラムを示します。
               int n1 = 8 - b;
               int n2 = 8;
               int n3 = n - (n1 + n2);
               int temp1 = (x[a] & mask[n1])  << (n2 + n3);
               int temp2 = x[a + 1] << n3;
               int temp3 = (x[a + 2] >> (24 - b - n));
               int result = temp1 | temp2 | temp3;
最終更新:2012年03月14日 05:37
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。