翻转整数的二进制位

原文连接:http://blog.csdn.net/gqtcgq/article/details/50533183


        一个无符号的整数,如果需要翻转其二进制位,可以采用下面的方法,以32位整数为例:

  1. unsigned int v; // 32-bit word to reverse bit order  
  2.   
  3. // swap odd and even bits  
  4. v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);  
  5.   
  6. // swap consecutive pairs  
  7. v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);  
  8.   
  9. // swap nibbles ...   
  10. v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);  
  11.   
  12. // swap bytes  
  13. v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);  
  14.   
  15. // swap 2-byte long pairs  
  16. v = ( v >> 16             ) | ( v               << 16);  

        第1步:对调相邻的1位(abcd efgh-> badc fehg)

  1. v = ((v >> 1) & 0x55555555) | ((v & 0x55555555)<< 1);  

        第2步:对调相邻的2位(abcd efgh-> cdab ghef)

  1. v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);  

        第3步:对调相邻的4位(abcd efgh-> efgh abcd)

  1. v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);  

        第4步:对调相邻的8位(相邻的字节)

  1. v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);  

        第5步:对调相邻的16位(相邻的两字节)

  1. v = ( v >> 16             ) | ( v               << 16);  

        经过上面的步骤,一个32位整数的二进制位已经翻转了。上面的对调步骤是互不干扰的,因此顺序可以倒过来,也就是先对调相邻16位,然后是8位、4位、2位和1位。所以,有人发明了下面的算法

  1. unsigned int s = sizeof(v) * CHAR_BIT; // bit size; must be power of 2   
  2. unsigned int mask = ~0;           
  3. while ((s >>= 1) > 0)   
  4. {  
  5.   mask ^= (mask << s);  
  6.   v = ((v >> s) & mask) | ((v << s) & ~mask);  
  7. }  

        上面代码中,每次mask计算得到的值分别是:0x0000ffff、0x00ff00ff、0x0f0f0f0f、0x33333333和0x55555555。而且,经过测试,针对上面的s和mask,((v << s) & ~mask)与((v & mask)<< s)是相同的。所以,上面的算法,就是最开始介绍的算法。

 

        这种算法的时间复杂度为O(lg(N))。比较适合N比较大的情况,Redis中,针对64位的实现如下:

  1. unsigned long rev(unsigned long v) {  
  2.     unsigned long s = 8 * sizeof(v); // bit size; must be power of 2  
  3.     unsigned long mask = ~0;  
  4.     while ((s >>= 1) > 0) {  
  5.         mask ^= (mask << s);  
  6.         v = ((v >> s) & mask) | ((v << s) & ~mask);  
  7.     }  
  8.     return v;  
  9. }  

http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值