C語言中的位操作(14)--反轉比特位


本篇文章主要講述幾種反轉比特位的方法:

將一個32位數:abcd efgh 轉置為hgfe dcba

1、常規方法

unsigned int v;     // 目標待轉置數
unsigned int r = v; //r保存反轉后的結果,開始獲取v的最低有效位
int s = sizeof(v) * CHAR_BIT - 1; // 剩余需要移位的比特位

for (v >>= 1; v; v >>= 1)
{   
  r <<= 1;
  r |= v & 1;
  s--;
}
r <<= s; // 當v的最高位為0的時候進行移位

原理:
   通過循環對v進行邏輯右移,每右移一位,通過v & 1取v的最低位,加到r的最低位,r左移

最后對v的最高位進行判斷,若原來v的最高位為0,則此時s=1,則再將v左移一位,若v的最高位為1,則s=0,則不進行任何操作。


2、查表

static const unsigned char BitReverseTable256[256] = 
{
#   define R2(n)     n,     n + 2*64,     n + 1*64,     n + 3*64
#   define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16)
#   define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 )
    R6(0), R6(2), R6(1), R6(3)
};

unsigned int v; // 反轉32位數,每次8位
unsigned int c; //c保存結果

操作一:

c = (BitReverseTable256[v & 0xff] << 24) | 
    (BitReverseTable256[(v >> 8) & 0xff] << 16) | 
    (BitReverseTable256[(v >> 16) & 0xff] << 8) |
    (BitReverseTable256[(v >> 24) & 0xff]);

原理:
通過嵌套宏定義構造一張表,BitReverseTable256[i]保存0~255進過反轉后的值,再分別取v中的第1~8、9~16、17~24、25~32位的值通過查表得到相應的反轉之后的值,在結合保存在r中

操作二:

unsigned char * p = (unsigned char *) &v;
unsigned char * q = (unsigned char *) &c;
q[3] = BitReverseTable256[p[0]]; 
q[2] = BitReverseTable256[p[1]]; 
q[1] = BitReverseTable256[p[2]]; 
q[0] = BitReverseTable256[p[3]];

原理較簡單,和操作一類似,這里采用指針進行。


3、64位乘法與模除法

unsigned char b; // reverse this (8-bit) byte
 
b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;

原理:

0x0202020202ULL: 0000 0010 0000 0010 0000 0010 0000 0010 0000 0010

0x010884422010ULL: 0000 0001 0000 1000 1000 0100 0100 0010 0010 0000 0001 0000

00000001 0000100010 0001000100 0010001000 0000010000

進行b * 0x0202020202ULL操作,變為: b0 b0 b0 b0 b0

  • 乘法(*)操作產生將8位字節模式復制5份到64位的輸出端
  • AND(&)操作選擇正確位置(反轉),相關聯到每10位一組
  • 乘法與“邏輯與”操作將源字中待反轉的比特位與10位一組的比特位相一致
  • 通過模除2^10-1,作用是結合64位數中的每10位組合(位置:0-9,10-19,20-29,……)

 4、64位乘法(無除法)

unsigned char b; // 目標反轉數
b = ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;

下面展示的bool變量a,b,c,d,e,f,g 和h,每一個由8位字節組成,注意第一個乘法是怎樣通過乘法復制將位模式展開,而最后的乘法將它們從右邊起每五字節一次地融合到一起

                                                                                        abcd efgh (-> hgfe dcba)
*                                                      1000 0000  0010 0000  0000 1000  0000 0010 (0x80200802)
-------------------------------------------------------------------------------------------------
                                            0abc defg  h00a bcde  fgh0 0abc  defg h00a  bcde fgh0
&                                           0000 1000  1000 0100  0100 0010  0010 0001  0001 0000 (0x0884422110)
-------------------------------------------------------------------------------------------------
                                            0000 d000  h000 0c00  0g00 00b0  00f0 000a  000e 0000
*                                           0000 0001  0000 0001  0000 0001  0000 0001  0000 0001 (0x0101010101)
-------------------------------------------------------------------------------------------------
                                            0000 d000  h000 0c00  0g00 00b0  00f0 000a  000e 0000
                                 0000 d000  h000 0c00  0g00 00b0  00f0 000a  000e 0000
                      0000 d000  h000 0c00  0g00 00b0  00f0 000a  000e 0000
           0000 d000  h000 0c00  0g00 00b0  00f0 000a  000e 0000
0000 d000  h000 0c00  0g00 00b0  00f0 000a  000e 0000
-------------------------------------------------------------------------------------------------
0000 d000  h000 dc00  hg00 dcb0  hgf0 dcba  hgfe dcba  hgfe 0cba  0gfe 00ba  00fe 000a  000e 0000
>> 32
-------------------------------------------------------------------------------------------------
                                            0000 d000  h000 dc00  hg00 dcb0  hgf0 dcba  hgfe dcba  
&                                                                                       1111 1111
-------------------------------------------------------------------------------------------------
                                                                                        hgfe dcba

 5、采用7部操作(非64位)

b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; 
                                                                                                     abcd efgh
*                                                                                          0000 1000 0000 0010
--------------------------------------------------------------------------------------------------------------
                                                                                      0abc defg h00a bcde fgh0  
&                                                                                     0010 0010 0001 0001 0000
--------------------------------------------------------------------------------------------------------------
                                                                                      00b0 00f0 000a 000e 0000       

                                                 
**************************************************************************************************************       

                                                                                                     abcd efgh
*                                                                                          1000 0000 0010 0000
--------------------------------------------------------------------------------------------------------------
                                                                                      defg h00a bcde fgh0 0000  
&                                                                                     1000 1000 0100 0100 0000
--------------------------------------------------------------------------------------------------------------
                                                                                      d000 h000 0c00 0g00 0000

**************************************************************************************************************

                                                                                      00b0 00f0 000a 000e 0000
|                                                                                     d000 h000 0c00 0g00 0000
--------------------------------------------------------------------------------------------------------------
                                                                                      d0b0 h0f0 0c0a 0g0e 0000
*                                                                                     0001 0000 0001 0000 0001
--------------------------------------------------------------------------------------------------------------
                                                                                      d0b0 h0f0 0c0a 0g0e 0000
                                                                            d0b0 h0f0 0c0a 0g0e 0000
                                                                  d0b0 h0f0 0c0a 0g0e 0000
--------------------------------------------------------------------------------------------------------------
                                                                  d0b0 h0f0 dcba hgfe dcba hgfe 0c0a 0g0e 0000 
>>16                                                                                        
--------------------------------------------------------------------------------------------------------------
                                                                                      d0b0 h0f0 dcba hgfe dcba
&                                                                                                    1111 1111
--------------------------------------------------------------------------------------------------------------
                                                                                                     hgfe dcba 

6、並行反轉N位數時間復雜度(5 * lg(N))

unsigned int v; // 32位目標數字
// 交換奇偶位比特
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
// 交換連續數對
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
// 一點點的交換 
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
// 交換字節
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
// 交換2字節長數對
v = ( v >> 16             ) | ( v               << 16);

 下面展示的32位變量由ABCD EFGH IJKL MNPQ abcd efgh ijkl mnpq組成

/*((v >> 1) & 0x55555555) */

                                                                       ABCD EFGH IJKL MNPQ abcd efgh ijkl mnpq
>>1
--------------------------------------------------------------------------------------------------------------
                                                                       0ABC DEFG HIJK LMNP Qabc defg hijk lmnp
&                                                                      0101 0101 0101 0101 0101 0101 0101 0101
--------------------------------------------------------------------------------------------------------------
                                                                       0A0C 0E0G 0I0K 0M0P 0a0c 0e0g 0i0k 0m0p

**************************************************************************************************************
/*((v & 0x55555555) << 1)*/

                                                                       ABCD EFGH IJKL MNPQ abcd efgh ijkl mnpq
&                                                                      0101 0101 0101 0101 0101 0101 0101 0101
--------------------------------------------------------------------------------------------------------------
                                                                       0B0D 0F0H 0J0L 0N0Q 0b0d 0f0h 0j0l 0n0q
<<1
--------------------------------------------------------------------------------------------------------------
                                                                       B0D0 F0H0 J0L0 N0Q0 b0d0 f0h0 j0l0 n0q0


**************************************************************************************************************

/*v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);*/
                                                                       0A0C 0E0G 0I0K 0M0P 0a0c 0e0g 0i0k 0m0p       |                                                                      B0D0 F0H0 J0L0 N0Q0 b0d0 f0h0 j0l0 n0q0
--------------------------------------------------------------------------------------------------------------
                                                                       BADC FEHG JILK NMQP badc fehg jilk nmqp

**************************************************************************************************************

/*((v >> 2) & 0x33333333)*/
                                                                       BADC FEHG JILK NMQP badc fehg jilk nmqp
>>2
--------------------------------------------------------------------------------------------------------------
                                                                       00BA DCFE HGJI LKNM QPba dcfe hgji lknm
&                                                                      0011 0011 0011 0011 0011 0011 0011 0011
--------------------------------------------------------------------------------------------------------------
                                                                       00BA 00FE 00JI 00NM 00ba 00fe 00ji 00nm

**************************************************************************************************************

/*((v & 0x33333333) << 2);*/

                                                                       BADC FEHG JILK NMQP badc fehg jilk nmqp
&                                                                      0011 0011 0011 0011 0011 0011 0011 0011
--------------------------------------------------------------------------------------------------------------
                                                                       00DC 00HG 00LK 00QP 00dc 00hg 00lk 00qp
<<2
--------------------------------------------------------------------------------------------------------------
                                                                       DC00 HG00 LK00 QP00 dc00 hg00 lk00 qp00

**************************************************************************************************************

/*((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);*/
                                                                       00BA 00FE 00JI 00NM 00ba 00fe 00ji 00nm       |                                                                      DC00 HG00 LK00 QP00 dc00 hg00 lk00 qp00
--------------------------------------------------------------------------------------------------------------
                                                                       DCBA HGFE LKJI QPNM dcba hgfe lkji qpnm


**************************************************************************************************************

/*((v >> 4) & 0x0F0F0F0F) */

                                                                       DCBA HGFE LKJI QPNM dcba hgfe lkji qpnm
>>4
--------------------------------------------------------------------------------------------------------------
                                                                       0000 DCBA HGFE LKJI QPNM dcba hgfe lkji
&                                                                      0000 1111 0000 1111 0000 1111 0000 1111
--------------------------------------------------------------------------------------------------------------
                                                                       0000 DCBA 0000 LKJI 0000 dcba 0000 lkji


**************************************************************************************************************

/*((v & 0x0F0F0F0F) << 4);*/

                                                                       DCBA HGFE LKJI QPNM dcba hgfe lkji qpnm
&                                                                      0000 1111 0000 1111 0000 1111 0000 1111
--------------------------------------------------------------------------------------------------------------
                                                                       0000 HGFE 0000 QPNM 0000 hgfe 0000 qpnm
<<4
--------------------------------------------------------------------------------------------------------------
                                                                       HGFE 0000 QPNM 0000 hgfe 0000 qpnm 0000
 

**************************************************************************************************************

/*((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);*/
                                                                       0000 DCBA 0000 LKJI 0000 dcba 0000 lkji
|                                                                      HGFE 0000 QPNM 0000 hgfe 0000 qpnm 0000
--------------------------------------------------------------------------------------------------------------
                                                                       HGFE DCBA QPNM LKJI hgfe dcba qpnm lkji

**************************************************************************************************************

/*((v >> 8) & 0x00FF00FF */

                                                                       HGFE DCBA QPNM LKJI hgfe dcba qpnm lkji
>>8
--------------------------------------------------------------------------------------------------------------
                                                                       0000 0000 HGFE DCBA QPNM LKJI hgfe dcba
&                                                                      0000 0000 1111 1111 0000 0000 1111 1111
--------------------------------------------------------------------------------------------------------------
                                                                       0000 0000 HGFE DCBA 0000 0000 hgfe dcba


**************************************************************************************************************

/*((v & 0x00FF00FF << 8);*/

                                                                       HGFE DCBA QPNM LKJI hgfe dcba qpnm lkji
&                                                                      0000 0000 1111 1111 0000 0000 1111 1111
--------------------------------------------------------------------------------------------------------------
                                                                       0000 0000 QPNM LKJI 0000 0000 qpnm lkji
<<8
--------------------------------------------------------------------------------------------------------------
                                                                       QPNM LKJI 0000 0000 qpnm lkji 0000 0000
 

**************************************************************************************************************

/*((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);*/
                                                                       0000 0000 HGFE DCBA 0000 0000 hgfe dcba
|                                                                      QPNM LKJI 0000 0000 qpnm lkji 0000 0000
--------------------------------------------------------------------------------------------------------------
                                                                       QPNM LKJI HGFE DCBA qpnm lkji hgfe dcba


**************************************************************************************************************

/*v = ( v >> 16             ) | ( v               << 16);*/

                                                                       QPNM LKJI HGFE DCBA qpnm lkji hgfe dcba
>>16                                                                   
--------------------------------------------------------------------------------------------------------------
                                                                       0000 0000 0000 0000 QPNM LKJI HGFE DCBA


                                                                       QPNM LKJI HGFE DCBA qpnm lkji hgfe dcba
<<16                                                                   
--------------------------------------------------------------------------------------------------------------
                                                                       qpnm lkji hgfe dcba 0000 0000 0000 0000 

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                                                                       0000 0000 0000 0000 QPNM LKJI HGFE DCBA
|                                                                      qpnm lkji hgfe dcba 0000 0000 0000 0000
--------------------------------------------------------------------------------------------------------------
                                                                       qpnm lkji hgfe dcba QPNM LKJI HGFE DCBA


下面的變版本時間復雜度也是O(lg(N)),但是需要更多的操作來反轉V

unsigned int s = sizeof(v) * CHAR_BIT; // 數的位數; 必須為2的冪 
unsigned int mask = ~0;         
while ((s >>= 1) > 0) 
{
  mask ^= (mask << s);
  v = ((v >> s) & mask) | ((v << s) & ~mask);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM