バイナリを逆にしたい
unsigned short gf_t = 44 // = 00101100
C言語の00110100で。ビット単位の演算子を使用して、どのようにそれを行うことができますか?
pdta:私のコンピューターは32ビットパターンです。
バイナリを逆にしたい
unsigned short gf_t = 44 // = 00101100
C言語の00110100で。ビット単位の演算子を使用して、どのようにそれを行うことができますか?
pdta:私のコンピューターは32ビットパターンです。
疑わしい場合は、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));
}
あなたはこのようにそれをすることができます(v
16ビットの数です):
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);
あなたはここでこのようなより多くのトリックを見つけることができます。このコードスニペットを使用したideoneへのリンクは次のとおりです。
これを理解しようとしている場合は、例で使用されている「マジックナンバー」のバイナリ表現を記述してください。
0x5555
は0101010101010101
0x3333
は0011001100110011
0x0F0F
は0000111100001111
0x00FF
は0000000011111111
この&
操作により、「不要な」ビットがクリアされます。シフトは、マスキング操作によって開かれた「ゼロギャップ」上に目的のパーツを再配置し、最後に|
2つのパーツを再結合します。
通常and
、LSBを取得するには1を入力します。Or
結果にそれ。結果を少し左にシフトし、入力を少し右にシフトします。合計32回繰り返します。
バイナリは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;
}