配列から任意のビット数のデータを取り出す方法 – プログラミング – Home

配列から任意のビット数のデータを取り出...
 
通知
すべてクリア

配列から任意のビット数のデータを取り出す方法


773
 773
(@773)
ゲスト
結合: 19年前
投稿: 3
Topic starter  

初めて質問をさせてもらいます。

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;

}

ちなみに
ポインタをビット単位で移動して、任意のビット数を
読み込む事は可能でしょうか?


引用解決済
トピックタグ
reshia
 reshia
(@reshia)
ゲスト
結合: 20年前
投稿: 117
 

よくわからないのですが、
>ビット演算子を調べて下記のプログラムを作ってみたのですが
このプログラムではダメだったということでしょうか?

>任意のビットデータが BYTEの配列に並んでいるデータから
>それぞれのビットデータを取り出したいと考えています。
たとえば、
10101010111010101101000110101011
というビットの並びが、配列Dataの中に8ビットずつ入っていて、つまり
[0] = 10101010
[1] = 11101010
[2] = 11010001
[3] = 10101011
となっていて、ここから、任意のビット数(Bit)分だけのデータを取り出したい
そういうことでしょうか?


返信引用
reshia
 reshia
(@reshia)
ゲスト
結合: 20年前
投稿: 117
 

あ、だから、
たとえば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
となるということでしょうか?


返信引用
まきじ
 まきじ
(@まきじ)
ゲスト
結合: 19年前
投稿: 20
 

共用体とかどうでしょうか?

union {
BYTE Buf[4];
struct {
unsigned int bit0:1;
:
:
unsigned int bit31:1;
};
};


返信引用
773
 773
(@773)
ゲスト
結合: 19年前
投稿: 3
Topic starter  

reshiaさん
ご返答ありがとうございます。
考え方は、そのとうりです。

説明不足で申し訳ありません。

目的の結果を得るために、試行錯誤し
今回初めて、ビット演算子を利用しました。

もっと一般的な方法などが在るのではないかと
思い、質問させていただきました。

膨大な量のデータを処理したいので、少しでも
動作を速くしたいと考えております。

何か、助言等ありましたら よろしくお願いします。


返信引用
reshia
 reshia
(@reshia)
ゲスト
結合: 20年前
投稿: 117
 

# 私が考えたのは・・
# 間違っているかもしれないので突っ込みよろしくおねがいします
オリジナル(?)のビット列の下位ビットが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]に入れるだけです。

がんばってください。


返信引用
tib
 tib
(@tib)
ゲスト
結合: 22年前
投稿: 468
 

> 膨大な量のデータを処理したいので、
> 少しでも動作を速くしたいと考えております。
> 何か、助言等ありましたら よろしくお願いします。
膨大、というのが実際どの程度のレベルなのか解りませんが、速さよりもまずは動くもの
を作った方がいいのではないでしょうか。より速いものを...とあれこれ悩んでいる時間
と、とりあえず動くものを動かしたまま放っておく時間とを比べたら、どちらが多くなる
でしょうね?

ちょっとおもしろそうだったので、こんなのを作ってみました。参考になりますか?

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;
}


返信引用
773
 773
(@773)
ゲスト
結合: 19年前
投稿: 3
Topic starter  

ご返答ありがとうございます。

皆さんのご返答上手く利用できず、苦戦中です。

分かりにくくて申し訳ありませんが..説明を加えて
考えをまとめてみます。

ビットの並びは下記のようになります。

オリジナルのデータが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

一個一個並び替えるしかないのでしょうか?
自分は何か考え違いをしているのでしょうか?


返信引用
まきじ
 まきじ
(@まきじ)
ゲスト
結合: 19年前
投稿: 20
 

>計算過程で
>共用体のビットフィールドや、
>ポインタで移動して 読み込むとビット並びが
>求めたい並びとは、逆になってしまいます。

共用体で、下位ビットからでも、上位ビットからでも
取り出せると思いますが?


返信引用
reshia
 reshia
(@reshia)
ゲスト
結合: 20年前
投稿: 117
 

# 最終的な目標からはズレてるかも
標準ライブラリにあるものを使えば、
一応、ビット列を表せるので、
もしよければこちらを。

bitset:実行時にサイズを変更できない
vector<bool>:演算ができない(a&bとか)
valarray<bool>:基本的な演算しかない(シフトがなかったり)

あと、BOOSTライブラリを使えば、
dynamic_bitset
というものがあります。
お薦めはこちら。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> pDW=(DWORD*)(pByte)
>
> pDWのビットの並びの結果
> 00010000 00100000 10000000 00000010
>
> 出てきてほしい並び
> 00000010 10000000 00100000 00010000

エンディアン(ビックエンディアン、リトルエンディアン)
について調べてみてください。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました