简体   繁体   English

以32位int反转每4位

[英]Reverse every 4bits in in 32 bit int

Reverse every bits in each 4 bit, eg: 反转每4位中的每个位,例如:

0101 1011 1100 0110 becomes
1010 1101 0011 0110

Another: 另一个:

1010 1100 0101 1100 becomes
0101 0011 1010 0011

I can think to reverse all 32 bit as below: 我可以认为将所有32位都反转,如下所示:

unsigned int reverseBits(unsigned int num)
{
    unsigned int count = sizeof(num) * 8 - 1;
    unsigned int reverse_num = num;

    num >>= 1; 
    while(num)
    {
       reverse_num <<= 1;       
       reverse_num |= num & 1;
       num >>= 1;
       count--;
    }
    reverse_num <<= count;
    return reverse_num;
}

But how to solve the above problem? 但是如何解决以上问题呢?

You can take the algorithm for complete bit-reversal , and delete a couple of steps, leaving you with just: (not tested) 您可以采用该算法进行完全位反转 ,然后删除几个步骤,剩下的只是:(未经测试)

x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);  // swap odd/even bits
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);  // swap groups of 2

Obviously that assumes unsigned ints are 32 bits. 显然,假定无符号整数为32位。

1. Lookup-table to reverse nibbles. 1.查找表以反转半字节。 The i -th element gives the nibble-reversed version of i , where i is an unsigned byte: i个元素给出的半字节反转的版本i ,其中i是一个无符号字节:

static const unsigned char lut[] = {
  0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 
  0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F, 
  0x80, 0x88, 0x84, 0x8C, 0x82, 0x8A, 0x86, 0x8E, 
  0x81, 0x89, 0x85, 0x8D, 0x83, 0x8B, 0x87, 0x8F, 
  0x40, 0x48, 0x44, 0x4C, 0x42, 0x4A, 0x46, 0x4E, 
  0x41, 0x49, 0x45, 0x4D, 0x43, 0x4B, 0x47, 0x4F, 
  0xC0, 0xC8, 0xC4, 0xCC, 0xC2, 0xCA, 0xC6, 0xCE, 
  0xC1, 0xC9, 0xC5, 0xCD, 0xC3, 0xCB, 0xC7, 0xCF, 
  0x20, 0x28, 0x24, 0x2C, 0x22, 0x2A, 0x26, 0x2E, 
  0x21, 0x29, 0x25, 0x2D, 0x23, 0x2B, 0x27, 0x2F, 
  0xA0, 0xA8, 0xA4, 0xAC, 0xA2, 0xAA, 0xA6, 0xAE, 
  0xA1, 0xA9, 0xA5, 0xAD, 0xA3, 0xAB, 0xA7, 0xAF, 
  0x60, 0x68, 0x64, 0x6C, 0x62, 0x6A, 0x66, 0x6E, 
  0x61, 0x69, 0x65, 0x6D, 0x63, 0x6B, 0x67, 0x6F, 
  0xE0, 0xE8, 0xE4, 0xEC, 0xE2, 0xEA, 0xE6, 0xEE, 
  0xE1, 0xE9, 0xE5, 0xED, 0xE3, 0xEB, 0xE7, 0xEF, 
  0x10, 0x18, 0x14, 0x1C, 0x12, 0x1A, 0x16, 0x1E, 
  0x11, 0x19, 0x15, 0x1D, 0x13, 0x1B, 0x17, 0x1F, 
  0x90, 0x98, 0x94, 0x9C, 0x92, 0x9A, 0x96, 0x9E, 
  0x91, 0x99, 0x95, 0x9D, 0x93, 0x9B, 0x97, 0x9F, 
  0x50, 0x58, 0x54, 0x5C, 0x52, 0x5A, 0x56, 0x5E, 
  0x51, 0x59, 0x55, 0x5D, 0x53, 0x5B, 0x57, 0x5F, 
  0xD0, 0xD8, 0xD4, 0xDC, 0xD2, 0xDA, 0xD6, 0xDE, 
  0xD1, 0xD9, 0xD5, 0xDD, 0xD3, 0xDB, 0xD7, 0xDF, 
  0x30, 0x38, 0x34, 0x3C, 0x32, 0x3A, 0x36, 0x3E, 
  0x31, 0x39, 0x35, 0x3D, 0x33, 0x3B, 0x37, 0x3F, 
  0xB0, 0xB8, 0xB4, 0xBC, 0xB2, 0xBA, 0xB6, 0xBE, 
  0xB1, 0xB9, 0xB5, 0xBD, 0xB3, 0xBB, 0xB7, 0xBF, 
  0x70, 0x78, 0x74, 0x7C, 0x72, 0x7A, 0x76, 0x7E, 
  0x71, 0x79, 0x75, 0x7D, 0x73, 0x7B, 0x77, 0x7F, 
  0xF0, 0xF8, 0xF4, 0xFC, 0xF2, 0xFA, 0xF6, 0xFE, 
  0xF1, 0xF9, 0xF5, 0xFD, 0xF3, 0xFB, 0xF7, 0xFF
};

2. Function to reverse the nibbles. 2.反转半字节的功能。 It applies the lookup-table to every byte of an unsigned 4-byte integer: 它将查找表应用于无符号4字节整数的每个字节:

unsigned reverse_nibbles(unsigned i) {
  return (lut[(i & 0xFF000000) >> 24] << 24) |
         (lut[(i & 0x00FF0000) >> 16] << 16) |
         (lut[(i & 0x0000FF00) >>  8] <<  8) |
         (lut[ i & 0x000000FF       ]      );
}

Test results ( ideone ): 测试结果( ideone ):

0000 0000 0000 0000 0101 1011 1100 0110
0000 0000 0000 0000 1010 1101 0011 0110

0000 0000 0000 0000 1010 1100 0101 1100
0000 0000 0000 0000 0101 0011 1010 0011

1100 1010 1111 1110 1011 1010 1011 1110
0011 0101 1111 0111 1101 0101 1101 0111

The lookup table was pre-calculated this way ( ideone ): 查找表是以这种方式预先计算的( ideone ):

#include <stdio.h>

int main() {
  unsigned i, j;
  for (i = 0; i < 256; ++i) {
    j = ((i & 0x01) << 3) | 
        ((i & 0x02) << 1) | 
        ((i & 0x04) >> 1) | 
        ((i & 0x08) >> 3) |
        ((i & 0x10) << 3) |
        ((i & 0x20) << 1) |
        ((i & 0x40) >> 1) |
        ((i & 0x80) >> 3);
    printf("0x%02X, ", j);
    if (((i + 1) % 8) == 0)
      printf("\n");
  }
  return 0;
}

Use code similar to what you have for each run of 4 bits, shifting each reversed nibble into the final result. 使用类似于您每次运行的4位代码,将每个反向的半字节移到最终结果中。

You could have 1 version of your code extract & replace each run of 4 bits (shifting by 4 bits with each iteration), and calling a different version that takes a 4-bit value & reverses those 4 bits (by setting count to 3, I believe). 您可以提取一个版本的代码,并替换每次运行的4位(每次迭代移动4位),然后调用采用4位值并反转这4位的其他版本(将count设置为3,我相信)。

我每4位交换一次的答案如下:

num = ((num&0F0F0F0F)<<4)|((num>>4)&0F0F0F0F);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM