初めて質問をさせてもらいます。
VC++6.0 MFC Windows2000で作業をしています。
任意のビットデータが BYTEの配列に並んでいるデータから
それぞれのビットデータを取り出したいと考えています。
ビット演算子を調べて下記のプログラムを作ってみたのですが
何か良い方法はないでしょうか?
BYTE Bit;
BYTE Buf[4];
DWORD DataNumber;
DWORD i,Temp,Temp2,Temp_s,Temp_a;
BYTE Data[500]; //データが詰まっているとして
DWORD Data2[500]; //この配列に取り出したい
Bit=17; //データのビット数(任意)
DataNumber=100; //データの個数(任意)
for(i=0;i<DataNumber;i++){
Temp=i*Bit;
Temp_s=Temp/8;
Temp_a=Temp%8;
Buf[0]=Data[Temp_s+0];
Buf[1]=Data[Temp_s+1];
Buf[2]=Data[Temp_s+2];
Buf[3]=Data[Temp_s+3];
Temp2=(Buf[0]<<24)+(Buf[1]<<16)+(Buf[2]<<8)+Buf[3];
Temp2=Temp2<<Temp_a;
Temp2=Temp2>>(32-Bit);
Data2[i]=Temp2;
}
ちなみに
ポインタをビット単位で移動して、任意のビット数を
読み込む事は可能でしょうか?
よくわからないのですが、
>ビット演算子を調べて下記のプログラムを作ってみたのですが
このプログラムではダメだったということでしょうか?
>任意のビットデータが BYTEの配列に並んでいるデータから
>それぞれのビットデータを取り出したいと考えています。
たとえば、
10101010111010101101000110101011
というビットの並びが、配列Dataの中に8ビットずつ入っていて、つまり
[0] = 10101010
[1] = 11101010
[2] = 11010001
[3] = 10101011
となっていて、ここから、任意のビット数(Bit)分だけのデータを取り出したい
そういうことでしょうか?
あ、だから、
たとえば3ビットずつ取り出したいなら、
Data2[0]=101
Data2[1]=010
Data2[2]=101
Data2[3]=110
Data2[4]=101
Data2[5]=011
Data2[6]=010
Data2[7]=001
Data2[8]=101
Data2[9]=010
Data2[10]=11
となるということでしょうか?
共用体とかどうでしょうか?
union {
BYTE Buf[4];
struct {
unsigned int bit0:1;
:
:
unsigned int bit31:1;
};
};
reshiaさん
ご返答ありがとうございます。
考え方は、そのとうりです。
説明不足で申し訳ありません。
目的の結果を得るために、試行錯誤し
今回初めて、ビット演算子を利用しました。
もっと一般的な方法などが在るのではないかと
思い、質問させていただきました。
膨大な量のデータを処理したいので、少しでも
動作を速くしたいと考えております。
何か、助言等ありましたら よろしくお願いします。
# 私が考えたのは・・
# 間違っているかもしれないので突っ込みよろしくおねがいします
オリジナル(?)のビット列の下位ビットがData[]配列の若い要素に入っている
つまり
... Data[3] Data[2] Data[1] Data[0]
という感じにビットが格納されているものとして・・。
SS0)
普通にint型の3-7ビット(計5ビット)を取り出したいときは、
「(i>>3)&0x1F」で取り出せます。
これと同じような処理を行います。
SS1)
Bit=17-bitずつ取り出すとき、
まず最初は(つまりforループのi=0のとき)、
0ビット目から16ビット目までを取り出してData2[0]に格納するわけです。
(i番目ならiビット目から(i+Bit-1)ビット目まで)
> h = i;
> t = i+Bit-1;
# h:head, t:tail
とすると、hビット目がData[]配列のどの要素に入っているかをまず調べます。
少し考えればわかると思うので、割愛します。
SS2)
hビット目がData[index_h]に入っていたとします。
そこからBitビット分のデータを取り出すのですが、単純にはできません。
tビット目がData[index_h]にあれば単純なのですが・・(SS0と同様の操作で良い)
とりあえず、Data[index_h]で必要なデータだけ取り出します。
必要なデータというのは、Data[index_h]は8-bitの情報を持っていますが
実際のところ、Data[index_h]の (h%8) ~ (h%8+Bit-1)のデータを取り出します。
たとえば、Bit=5, i=1のときは、h=5, t=9 で、index_h=0になりますが
実際には、Data[0]の5-7ビット目とData[1]の0-1ビット目が目的のビットに当たります。
とまぁ、こんな感じで書きすぎるのもよくないと思いますので、
後は・・、わかりますよね?
気をつけるのは、index_h番目からデータを取り出すときと、
Data[]配列の最後の方からデータを取り出すときに、配列オーバーしないことです。
取り出せたら、Data2[i]に入れるだけです。
がんばってください。
> 膨大な量のデータを処理したいので、
> 少しでも動作を速くしたいと考えております。
> 何か、助言等ありましたら よろしくお願いします。
膨大、というのが実際どの程度のレベルなのか解りませんが、速さよりもまずは動くもの
を作った方がいいのではないでしょうか。より速いものを...とあれこれ悩んでいる時間
と、とりあえず動くものを動かしたまま放っておく時間とを比べたら、どちらが多くなる
でしょうね?
ちょっとおもしろそうだったので、こんなのを作ってみました。参考になりますか?
DWORD Cxxxxx::extractBits(BYTE *pByte, int nFrom, int nLength)
{
DWORD dwRet = 0;
DWORD dwMask = 0xffffffff;
DWORD *pDW;
dwMask <<= (32 - nLength);
dwMask >>= nFrom;
pDW = (DWORD*)(pByte + (nFrom/8));
dwRet = *pDW & dwMask;
dwRet >>= (32 - nFrom - nLength);
return dwRet;
}
ご返答ありがとうございます。
皆さんのご返答上手く利用できず、苦戦中です。
分かりにくくて申し訳ありませんが..説明を加えて
考えをまとめてみます。
ビットの並びは下記のようになります。
オリジナルのデータが10ビットの場合
ビット並び 000000101000000000100000000100..
↓
8ビット 00000010 10000000 00100000 000100..
↓
正の整数に変換 2 128 32 ..
↓
BYTE配列読に読み込み Data[0]=2 Data[1]=128 Data[2]=32 Data[3]=..
↓
10ビットに分解 0000001010 0000000010 0000000100 ..
↓
正の整数に変換 10 2 4 ..
↓
DWORD配列に代入 Data2[0]=10 Data2[1]=2 Data2[2]=4
最終的に 配列Data2に正の整数値として代入したいと考えています。
ビットは、右から左に増え、上位ビットがData[]配列の若い方になります
計算過程で
共用体のビットフィールドや、
ポインタで移動して 読み込むとビット並びが
求めたい並びとは、逆になってしまいます。
例えば、
BYTE buf[4];
BYTE *pByte;
DWORD *pDW;
buf[0]=2; 00000010
buf[1]=128; 10000000
buf[2]=32; 00100000
buf[3]=16; 00010000
pByte=buf;
pDW=(DWORD*)(pByte)
pDWのビットの並びの結果
00010000 00100000 10000000 00000010
出てきてほしい並び
00000010 10000000 00100000 00010000
一個一個並び替えるしかないのでしょうか?
自分は何か考え違いをしているのでしょうか?
>計算過程で
>共用体のビットフィールドや、
>ポインタで移動して 読み込むとビット並びが
>求めたい並びとは、逆になってしまいます。
共用体で、下位ビットからでも、上位ビットからでも
取り出せると思いますが?
# 最終的な目標からはズレてるかも
標準ライブラリにあるものを使えば、
一応、ビット列を表せるので、
もしよければこちらを。
bitset:実行時にサイズを変更できない
vector<bool>:演算ができない(a&bとか)
valarray<bool>:基本的な演算しかない(シフトがなかったり)
あと、BOOSTライブラリを使えば、
dynamic_bitset
というものがあります。
お薦めはこちら。
> pDW=(DWORD*)(pByte)
>
> pDWのビットの並びの結果
> 00010000 00100000 10000000 00000010
>
> 出てきてほしい並び
> 00000010 10000000 00100000 00010000
エンディアン(ビックエンディアン、リトルエンディアン)
について調べてみてください。