0

バイナリを逆にしたい

unsigned short gf_t  = 44 // = 00101100

C言語の00110100で。ビット単位の演算子を使用して、どのようにそれを行うことができますか?

pdta:私のコンピューターは32ビットパターンです。

4

4 に答える 4

6

疑わしい場合は、BitTwiddlingHacksのページを参照してください。実際、そこにはあなたが望むことをする非常に単純なアルゴリズムを見つけることができます...

明らかな方法でビットを逆にする

unsigned int v;     // input bits to be reversed
unsigned int r = v; // r will be reversed bits of v; first get LSB of v
int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end

for (v >>= 1; v; v >>= 1)
{   
  r <<= 1;
  r |= v & 1;
  s--;
}
r <<= s; // shift when v's highest bits are zero 

2004年10月15日、MichaelHoisieは元のバージョンのバグを指摘しました。Randal E. Bryantは、2005年5月3日に余分な操作を削除することを提案しました。BehdadEsfabodは、2005年5月18日にループの1回の反復を排除するわずかな変更を提案しました。その後、2007年2月6日に、LiyongZhouはループするより良いバージョンを提案しました。 vは0ではないため、すべてのビットを反復処理するのではなく、早期に停止します。

ただし、そこにはいくつかの気の利いたアプローチが文書化されています。あなたはそれらを調べて、学習のためにそれらを理解しようとすることができます:-)たとえば、ここに1つの特定の興味深い形式があります...

5 * lg(N)演算でNビット量を並列に反転します。

unsigned int v; // 32-bit word to reverse bit order

// swap odd and even bits
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
// swap nibbles ... 
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
// swap 2-byte long pairs
v = ( v >> 16             ) | ( v               << 16);

の場合、適切な使用法では最初の4つの転置のみが必要になることに注意してください。次のように参照してsizeof(unsigned short) * CHAR_BITください。16

unsigned short v;

// swap odd and even bits
v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2);
// swap nibbles ... 
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8);

そうは言っても、(利用可能な場合は)単に使用しないのはなぜuint16_tですか?

これが実際の例です(ideoneを参照):

#include <stdio.h>
#include <assert.h>
#include <stdint.h>

inline uint16_t reverse(uint16_t v) {
  v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1); /* swap odd/even bits */
  v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2); /* swap bit pairs */
  v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4); /* swap nibbles */
  v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8); /* swap bytes */
  return v;
}

main() {
  uint16_t gf_t = 44;
  printf("%hu\n", reverse(gf_t));
}
于 2012-09-10T19:07:21.330 に答える
5

あなたはこのようにそれをすることができます(v16ビットの数です):

v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1);
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2);
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4);
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8);
  • 最初の行は奇数ビットと偶数ビットを交換します
  • 2行目は連続するペアを交換します
  • 3行目は4ビットのグループを交換します
  • 最後の行は2バイトを交換します

あなたはここでこのようなより多くのトリックを見つけることができます。このコードスニペットを使用したideoneへのリンクは次のとおりです。

これを理解しようとしている場合は、例で使用されている「マジックナンバー」のバイナリ表現を記述してください。

  • 0x55550101010101010101
  • 0x33330011001100110011
  • 0x0F0F0000111100001111
  • 0x00FF0000000011111111

この&操作により、「不要な」ビットがクリアされます。シフトは、マスキング操作によって開かれた「ゼロギャップ」上に目的のパーツを再配置し、最後に|2つのパーツを再結合します。

于 2012-09-10T19:09:20.517 に答える
1

通常and、LSBを取得するには1を入力します。Or結果にそれ。結果を少し左にシフトし、入力を少し右にシフトします。合計32回繰り返します。

于 2012-09-10T19:05:46.743 に答える
0

バイナリは0000000000101100です-ショートには16ビットがあります。

//ここに行くを含む

int main() {

unsigned short gf_t = 44; cout << hex << gf_t << endl;

unsigned short gf_r = 0;
for ( int iter = 0; iter < sizeof(short) * 8; ++iter )
{
unsigned short tmp = gf_t;
tmp = tmp & 1;
gf_r = (gf_r << 1 ) | tmp;
gf_t = gf_t >> 1;
}

cout << hex << gf_r << endl;

}

于 2012-09-10T19:29:43.767 に答える