よろしくお願いいたします。
例えば、
unsigned int x=0x20000が入っている時に、
xを10進数の4にしたいのです。
xを18bitデータとしたときに
010000000000000000(18bit)
の時に、
000000000000000010(18bit)
として扱いたいのです。 つまりMSBとLSBの入れ替え(??)
のようなことをしたいのです。
どうしたら良いのでしょう?
よろしくお願いいたします。
失礼いたします。
--
// 沖野 幸治 OKINO Kouji
// 株式会社コア 北海道カンパニー
// E-mail: ok...@core.co.jp
union Abc {
int x;
struct Word {
unsigned short h;
unsigned short l;
};
};
とでもしておいて、
unsigned short tmp;
union Abc abc;
abc.x = 何か入れる;
tmp = abc.Word.h;
abc.Word.h = abc.Word.l;
abc.Word.l = tmp;
とすれば、見事に abc.x の上位下位が入れ替わると思うのですが。
パディングの問題もあり、うまくいかない事もあります。その時はデバッガで
コンパイルされたコードを見て見ましょう。
takashi izumi <iz...@wtlab.sony.co.jp> wrote in message
news:7spjqa$1ej$1...@tdcgw.tdc.sony.co.jp...
> 例えば、
> unsigned int x=0x20000が入っている時に、
>
> xを10進数の4にしたいのです。
>
> xを18bitデータとしたときに
>
> 010000000000000000(18bit)
> の時に、
> 000000000000000010(18bit)
>
> として扱いたいのです。 つまりMSBとLSBの入れ替え(??)
> のようなことをしたいのです。
--
株式会社 国土基礎 伊東
-- ISO9002 --
E-mail:koku...@tym.fitweb.or.jp
struct {
unsigned short h,
} Word;
のように、struct文の後ろに変数名を入れてください。
タグ部ではコンパイルエラーが出ます。
kokudo-h <koku...@tym.fitweb.or.jp> wrote in message
news:7spmqd$3se$1...@tymwsv07.fitweb.or.jp...
> unsigned shortの大きさ = unsigned int の半分だということが
> 分かっている場合に限り、
>
> union Abc {
> int x;
> struct Word {
> unsigned short h;
> unsigned short l;
> };
> };
>
> とでもしておいて、
>
> unsigned short tmp;
> union Abc abc;
>
> abc.x = 何か入れる;
> tmp = abc.Word.h;
> abc.Word.h = abc.Word.l;
> abc.Word.l = tmp;
>
> とすれば、見事に abc.x の上位下位が入れ替わると思うのですが。
>
--
> xを18bitデータとしたときに
>
> 010000000000000000(18bit)
> の時に、
> 000000000000000010(18bit)
>
> として扱いたいのです。 つまりMSBとLSBの入れ替え(??)
> のようなことをしたいのです。
0と1の並びだと、ちょっと分からなくなるので、各ビットを英文字に
対応させ abcdefghijklmnopqr としておきます。
これを rqponmlkjihgfedcba にしたいならば、ビット操作を使って行います。
いわゆるエンディアンを変更したいならば、やはりビット操作でも行えます
が、それよりもunionを利用したり、(もしあるなら)swab関数などのバイト
単位の交換処理を使うなどして、バイト単位に操作したほうが簡単でしょうね。
(9ビットが1単位とかだと、またヤッカイかもしれない)
で、和泉さんは、どちらの操作が御所望ですか?
----- Takeshi Shigihara
Office cyg...@masternet.or.jp
Home cyg...@po.jah.ne.jp -----
問題の意味がよく分からないのですが、
100000000000000000 を 000000000000000100 にしたい。
010000000000000000 を 000000000000000010 にしたい。
すなわち、18ビットのデータを 3ビットずつ区切って、上位と下位だけを
反転したいということでしょうか。それなら、
unsigned int revbit(unsigned int x)
{
return (x&07)<<15 | x & 077770 | x>>15 & 07;
}
3ビットずつの区切りを全部反転したいのなら、
unsigned int revbit(unsigned int x)
{
return (x&07)<<15 | (x&070)<<9 | (x&0700)<<3
| x>>3 & 0700 | x>>9 & 070 | x>>15 & 07;
}
【テストプログラム】
void print(unsigned int x)
{
int n = 18;
while (--n >= 0)
putchar((x>>n & 1) + '0');
printf("[2], %06o[8], %05x[16]\n", x, x);
}
void func(unsigned int x)
{
print(x);
print(revbit(x));
}
int main()
{
func(0x20000);
func(0x10000);
return 0;
}
【実行結果】
100000000000000000[2], 400000[8], 20000[16]
000000000000000100[2], 000004[8], 00004[16]
010000000000000000[2], 200000[8], 10000[16]
000000000000000010[2], 000002[8], 00002[16]
--
坂本智彦 saka...@sm.sony.co.jp
In article <7spjqa$1ej$1...@tdcgw.tdc.sony.co.jp>
iz...@wtlab.sony.co.jp writes:
>和泉と申します。
>unsigned int x=0x20000が入っている時に、
>
>xを10進数の4にしたいのです。
>
>xを18bitデータとしたときに
>
> 010000000000000000(18bit)
>の時に、
> 000000000000000010(18bit)
>
>として扱いたいのです。 つまりMSBとLSBの入れ替え(??)
>のようなことをしたいのです。
こんなんでよろしいでしょうか?
#include <stdio.h>
unsigned int bit_reverse(unsigned int x, int width)
{
unsigned int y=0x0;
int i;
for( i=0; i< width; i++ ){
y |= x & 0x1;
x >>= 1;
y <<= 1;
}
return(y);
}
int main()
{
unsigned int x=0x20000; /* input */
printf("%x => %x\n", x, bit_reverse(x,18));
return(0);
}
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
x sato...@is.aist-nara.ac.jp x
x NAIST 情報科学科 藤原(秀)研 x
x 浮穴学慈 (うけなさとしげ) x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
<7spv4v$nbk$1...@voyager.aist-nara.ac.jp>の記事において
sato...@is.aist-nara.ac.jpさんは書きました。
> for( i=0; i< width; i++ ){
> if( x & 0x1 ) y |= 0x1;
> x >>= 1;
> y <<= 1;
> }
y <<= 1; の位置がおかしいのではないでしょうか?
y <<= 1;
if( x & 0x1 ) y |= 0x1;
x >>= 1;
だと思います。
FFT のように何度もやる必要があるならビット反転のテーブルを作ってしまう
方法もあります。例えば、奥村晴彦著「C 言語による最新アルゴリズム事典」
(技術評論社)の FFT の項など参考になるかと思います。
--
河村雅夫 (kawa...@aki.jest.co.jp)
In article <9909281811...@green.aki.jest.co.jp>
kawa...@aki.jest.co.jp writes:
>Subject の意味がいろいろに取れるますけど、 iz...@wtlab.sony.co.jp さんが
>書いている例から考えて全ビットを反転したいんでしょうね。
>FFT でしょうか?
>
><7spv4v$nbk$1...@voyager.aist-nara.ac.jp>の記事において
>sato...@is.aist-nara.ac.jpさんは書きました。
>
>> for( i=0; i< width; i++ ){
>> if( x & 0x1 ) y |= 0x1;
>> x >>= 1;
>> y <<= 1;
>> }
>
>y <<= 1; の位置がおかしいのではないでしょうか?
>
> y <<= 1;
> if( x & 0x1 ) y |= 0x1;
> x >>= 1;
>
>だと思います。
おっしゃる通りです。お恥ずかしい ^^;
0x20000 を 2 になると書いたり。
速攻で記事をキャンセルして、
y <<= 1;
y |= x & 0x1;
x >>= 1;
と直したつもりが、
y |= x & 0x1;
y <<= 1;
x >>= 1;
となっていたり。
和泉さんこんにちは。
ビットリバースの問題と解釈いたしました。
bit0 <-> bit17
bit1 <-> bit16
...
bit7 <-> bit10
bit8 <-> bit9
の結果を返します。
bitsizeにはこの場合ビットフィールドサイズ=18を入れて使用してください。
#include <stdio.h>
#include <assert.h>
unsigned long BitReverse(unsigned long l, int bitsize)
{
unsigned long m = 0;
int i;
assert(bitsize <= sizeof(long)*8); /* long より大きなビットサイズは扱え
ない。 */
for(i = 0; i < bitsize; i++)
{
m <<= 1;
m |= l & 0x01;
l >>= 1;
}
return m;
}
int main(int argc, char* argv[])
{
unsigned long l = 0x10000;
printf("%lx", BitReverse(l, 18));
return 0;
}
浮穴さんこんにちは
ほぼ同時に同様の関数を投稿いたしました。ただ気になったのは、C言語一般から言
うと、bit_reverse()の引数及び戻り値はunsigned longのほうが動作する環境がほん
の少し増えるような気がします。
unsigned long bit_reverse(unsigned long x, int width);
ですね。
テーブル参照バージョンです、使用環境によっては(^○^)高速化できるかもしれませ
ん(^○^)。
#include <stdio.h>
#include <assert.h>
unsigned long BitReverseA(unsigned long l, int bitsize)
{
unsigned long m = 0;
int i;
assert(bitsize <= sizeof(long)*8);
for(i = 0; i < bitsize; i++)
{
m <<= 1;
m |= l & 0x01;
l >>= 1;
}
return m;
}
unsigned char RTbl[256];
void MakeRTbl()
{
int i;
if (RTbl[255] == 0)
{
for(i = 0; i < 256; i++)
{
RTbl[i] = (unsigned char)BitReverseA(i, 8);
}
}
}
unsigned long BitReverse(unsigned long l, int bitsize)
{
unsigned long m = 0;
int i;
l <<= 8 - bitsize % 8;
i = (bitsize+7)/8;
assert(i <= sizeof(long)); /* long までを対象にしています */
assert(RTbl[255] == 0xff); /* テーブルは初期化されていなければなりませ
ん */
while( i-- )
{
m <<= 8;
m += RTbl[l & 0xff];
l >>= 8;
}
return m;
}
int main(int argc, char* argv[])
{
unsigned long l = 0x10000;
MakeRTbl();
> unsigned long BitReverse(unsigned long l, int bitsize)
> {
> unsigned long m = 0;
> int i;
>
> l <<= 8 - bitsize % 8;
> i = (bitsize+7)/8;
う~む。bitsize が 8 の倍数だとマズいような…
むりやり
l <<= 8 - ((bitsize -1) % 8 + 1);
かなあ(ただし bitsize > 0)。
それとも i を先にして l <<= i*8 - bitsize; か。
--
河村雅夫 (kawa...@aki.jest.co.jp)
> unsigned char RTbl[256];
>
> void MakeRTbl()
> {
マクロを利用して、コンパイル時にテーブルを用意するようにすれば、
MakeRTbl() は不要です。
#define t0(x) t1(x),t1(x+1)
#define t1(x) t2(x),t2(x+2)
#define t2(x) t3(x),t3(x+4)
#define t3(x) t4(x),t4(x+8)
#define t4(x) t5(x),t5(x+16)
#define t5(x) t6(x),t6(x+32)
#define t6(x) t7(x),t7(x+64)
#define t7(x) x,x+128
unsigned char RTbl[256] = { t0(0) };
--
坂本智彦 saka...@sm.sony.co.jp
> unsigned long BitReverse(unsigned long l, int bitsize)
> l <<= 8 - bitsize % 8;
これでは、bitsize が 8の倍数のとき、正しい結果が得られないのでは
ありませんか。
l <<= (32 - bitsize) % 8; にしたほうがよいのでは。
あるいは、l <<= -bitsize & 7;
--
坂本智彦 saka...@sm.sony.co.jp
"kokudo-h" <koku...@tym.fitweb.or.jp> wrote in
message <7spmqd$3se$1...@tymwsv07.fitweb.or.jp>:
> union Abc {
> int x;
> struct Word {
> unsigned short h;
> unsigned short l;
> };
> };
数年前、こういう風な union を使った方法でエンディアンを変えよ
うと試みた事があります。
# 自作ツールを動かしていた HP-UX が、680x0→PA-RISC になって
# エンディアンが変わった為です。
この例の名前で説明すれば、「h、l には書き込み」で「x には読み
出し」だけをして、バラけたデータを1つにまとめようとした訳で
す。
ところが、その時に使っていたコンパイラは「union なのに、アク
セス先オブジェクトが同一だとは思わなかった」様で、この方法だ
けでは成功しませんでした。
結局、union の変数を volatile にする事でしのぎました。
ま、そんな事もありますという例です。
Tabby as くろさわ
ta...@yk.rim.or.jp
$ fortune
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
-- Reverse the bits in a word.
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
[12],(6,9),0,0,2
(211/9880/17586)
In article <7sq07u$olg$2...@voyager.aist-nara.ac.jp>
sato...@is.aist-nara.ac.jp writes:
>こんなんでよろしいでしょうか?
>
>#include <stdio.h>
>
>unsigned int bit_reverse(unsigned int x, int width)
>{
> unsigned int y=0x0;
> int i;
>
> for( i=0; i< width; i++ ){
> y |= x & 0x1;
> x >>= 1;
> y <<= 1;
y <<= 1;
y |= x & 0x1;
x >>= 1;
の間違いです。
In article <7sq41o$ea0$1...@news.osaka.att.ne.jp>
cg_...@osa.att.ne.jp writes:
>河原@日本LSIカード(株)です。
>ほぼ同時に同様の関数を投稿いたしました。ただ気になったのは、C言語一般から言
>うと、bit_reverse()の引数及び戻り値はunsigned longのほうが動作する環境がほん
>の少し増えるような気がします。
おっしゃる通りだと思います。
#紙に書いてシミュレートしてみようかな。
Kazuo Fox Dohzono <doh...@hf.rim.or.jp> wrote in message
news:7sqstn$882$1...@news2.na.rim.or.jp...
> > つまりMSBとLSBの入れ替え
>
> $ fortune
> n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
> n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
> n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
> n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
> n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
>
> -- Reverse the bits in a word.
--
Kazuo Fox Dohzono wrote:
> > つまりMSBとLSBの入れ替え
>
> $ fortune
> n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
> n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
> n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
> n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
> n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
>
> -- Reverse the bits in a word.
>
これが18ビットだと、
001001001001001001b=
00 1001 0010 0100 1001b=09249h
010010010010010010b=
01 0010 0100 1001 0010b=12492h
100100100100100100b=
10 0100 1001 0010 0100b=24924h
000000111000000111b=
00 0000 1110 0000 0111b=00e07h
000111000000111000b=
00 0111 0000 0011 1000b=07038h
111000000111000000b=
11 1000 0001 1100 0000b=381c0h
000000000111111111b=
00 0000 0001 1111 1111b=001ffh
111111111000000000b=
11 1111 1110 0000 0000b=3fe00h
n = ((n >> 2) & 0x09249) | (n & 0x12492) | ((n << 2 ) & 0x24924);
n = ((n >> 6) & 0x00e07) | (n & 0x07038) | ((n << 6) & 0x381c0);
n = ((n >> 9) & 0x001ff) | ((n << 9) & 0x3fe00);
こうですかねぇ?
#なんでCって2進数を直接書けないんだろう(^^;
##それでも8進数で描いたほうがまだ楽だったか。
n = ((n >> 2) & 0111111) | (n & 0222222) | ((n << 2) & 0444444);
n = ((n >> 6) & 0007007) | (n & 0070070) | ((n << 6) & 0700700);
n = ((n >> 9) & 0000777) | ((n << 9) & 0777000);
かな?
--
cog...@sp.hudson.co.jp
株式会社ハドソン 第3開発部
熊岡 忍(Kumaoka Shinobu)
坂本智彦さんこんにちは。
> > l <<= 8 - bitsize % 8;
>
> これでは、bitsize が 8の倍数のとき、正しい結果が得られないのでは
> ありませんか。
>
> l <<= (32 - bitsize) % 8; にしたほうがよいのでは。
> あるいは、l <<= -bitsize & 7;
ううう、そのとうりm(__)m。
l <<= 8 - bitsize % 8;
を
l <<= -bitsize & 7;
に書き換えてください(^○^)。「l <<= (32 - bitsize) % 8;」は、32という固定値
が気に入らないし、「l <<= -bitsize & 7;」の方がほんの少し高速そうなのでこち
らにしましょ。
坂本智彦さんこんにちは。
> マクロを利用して、コンパイル時にテーブルを用意するようにすれば、
> MakeRTbl() は不要です。
おおお、すばらしい(^○^)。マジカルマクロ!!!。
ということで、以下がバグフィックスされた最終版です(^○^)。
坂本智彦さん、河村雅夫さん感謝(^○^)。
#include <stdio.h>
#include <assert.h>
/* Bit Reverse Subprogram */
#if 01
/* テーブル参照バージョン */
#define t0(x) t1(x),t1(x+1)
#define t1(x) t2(x),t2(x+2)
#define t2(x) t3(x),t3(x+4)
#define t3(x) t4(x),t4(x+8)
#define t4(x) t5(x),t5(x+16)
#define t5(x) t6(x),t6(x+32)
#define t6(x) t7(x),t7(x+64)
#define t7(x) x,x+128
unsigned long BitReverse(unsigned long l, int bitsize)
{
static unsigned char RTbl[256] = { t0(0) };
unsigned long m = 0;
int i;
assert(bitsize <= sizeof(long)*8); /* bitsizeが適性か */
l <<= -bitsize & 7;
i = (bitsize+7)/8;
while( i-- )
{
m <<= 8;
m += RTbl[l & 0xff];
l >>= 8;
}
return m;
}
#else
/* ビットシフトバージョン */
unsigned long BitReverse(unsigned long l, int bitsize)
{
unsigned long m = 0;
int i;
assert(bitsize <= sizeof(long)*8);
for(i = 0; i < bitsize; i++)
{
m <<= 1;
m |= l & 0x01;
l >>= 1;
}
return m;
}
#endif
/* Bit Reverse Subprogram End */
int main(int argc, char* argv[])
{
unsigned long l = 0x10000;
printf("%lx", BitReverse(l, 18));
return 0;
}
--- ノート ---
う~ん、2バージョン作ってみたけど、ビットシフトがテーブル引きを超えるス
ピードを出す環境ってあるのかな?。このままだとテーブル引きがバイトアクセスに
なるのでそこで遅くなる環境もあるだろうけど、そのときは「unsigned char
RTbl[256]」を「unsigned short RTbl[256]」とか「unsigned int RTbl[256]」に変
えたらいいことだしな~(+_+)。
--- ノート END ---
> これって、すごく高度なアルゴリズムなんでしょうか。
私も昔同じものを独立に考え付いたくらいですから高度ということはないでしょ
う. ちなみに私のバージョンでは
32bit -> 16bit ずつ上下入れ替え
16bit x 2 -> 8bit ずつ上下入れ替え x 2
8bit x 4 -> 4bit ずつ上下入れ替え x 4
…
と考えたので,
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
となりました. fortune 版はこれとは逆に先ず 1 ビット入れ替えて…という
感じだったのだろうと思います.
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
[12],(6,9),0,0,2
(212/9413/17070)
>>#なんでCって2進数を直接書けないんだろう(^^;
#define BIN ((((((((0
#define O *2+0)
#define I *2+1)
unsigned int n[]={
BIN O O O I I O O O,
BIN O O I O O I O O,
BIN O I O O O O I O,
BIN I O O O O O O I,
BIN I O O O O O O I,
BIN I I I I I I I I,
BIN I O O O O O O I,
BIN I O O O O O O I
};
みたいな感じでよければ。。
#なんとなく昔、MSXでかいたスプライトを
#思い出すような。
--
まつむらしげる。。
Kazuo Fox Dohzono <doh...@hf.rim.or.jp> wrote in message
news:7t17cd$rvm$1...@news2.na.rim.or.jp...
> 32bit -> 16bit ずつ上下入れ替え
> 16bit x 2 -> 8bit ずつ上下入れ替え x 2
> 8bit x 4 -> 4bit ずつ上下入れ替え x 4
> …
>
> と考えたので,
>
> n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
> n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
> n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
> n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
> n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
--
株式会社 国土基礎