學習筆記 詳解一種高效位反轉演算法
詳解一種高效位反轉演算法
位反轉
這裡的位反轉(Bit Reversal),指的是一個數的所有bit位依照中點對換位置,例如0b0101 0111 => 0b1110 1010。也可以叫二進位制逆序,按位逆序,位翻轉等等。
演算法原理
高效位反轉演算法原理:演算法運用了分治法(divide and conquer),以兩個bit位一組,對調相鄰的bit位;然後再以4個bit位為一組,分成左邊兩個bit位一段和右邊兩個bit位一段,然後這兩段相互對調;然後再以8個bit位為一組,以此類推,最後完成位反轉。
32位數的高效位反轉演算法實現
下面舉例一個32位數的高效位反轉演算法程式碼:
unsigned int reverse(unsigned int x)
{
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
return((x >> 16) | (x << 16));
}
下面進行逐行程式碼分析:
首先,我們要進行位反轉的是一個32位數,如下圖所示
分析第一行程式碼:
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
-
0xaaaaaaaa
0xaaaaaaaa 是從第0位開始,所有奇數位為1
0xaaaaaaaa = 0b10101010101010101010101010101010
-
x & 0xaaaaaaaa
x & 0xaaaaaaaa的結果如下圖所示:
(x & 0xaaaaaaaa) >> 1
右移一位後結果如下圖所示:
-
0x55555555
0x55555555是從第0位開始,所有偶數位為1
0x55555555 = 0b01010101010101010101010101010101
-
x & 0x55555555
x & 0x55555555的結果如下圖所示:
-
(x & 0x55555555) << 1
左移一位的結果如下圖所示:
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
然後兩個數或運算,結果如下圖所示:
第一行程式碼運算完成。
總結,x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
這行的程式碼就是以兩個bit位一組,對調相鄰的bit位。
圖解就是將下圖
轉換成
分析第二行程式碼:
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
目前x的數值為:
-
0xcccccccc
0xcccccccc是從第0位開始,0和1每隔兩位交替出現0
xcccccccc = 0b11001100110011001100110011001100 -
x & 0xcccccccc
x & 0xcccccccc的結果如下圖所示:
-
(x & 0xcccccccc) >> 2
右移兩位後結果如下圖所示:
-
0x33333333
0x33333333是從第0位開始,1和0每隔兩位交替出現
0x33333333 = 0b00110011001100110011001100110011 -
x & 0x33333333
x & 0x33333333的結果如下圖所示:
(x & 0x33333333) << 2
左移兩位後結果如下圖所示:
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
然後兩個數或運算,結果如下圖所示:
第二行程式碼運算完成。
總結,x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
這行的程式碼就是以4個bit位為一組,分成左邊兩個bit位一段和右邊兩個bit位一段,然後這兩段相互對調。
圖解就是將下圖
轉換成
分析第三行程式碼:
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
目前x的數值為:
-
0xf0f0f0f0
0xf0f0f0f0是從第0位開始,0和1每隔四位交替出現
0xf0f0f0f0= 0b11110000111100001111000011110000 -
x & 0xf0f0f0f0
x & 0xf0f0f0f0的結果如下圖所示:
-
(x & 0xf0f0f0f0) >> 4
右移四位後結果如下圖所示:
-
0x0f0f0f0f
0x0f0f0f0f是從第0位開始,1和0每隔四位交替出現
0x0f0f0f0f= 0b00001111000011110000111100001111
-
x & 0x0f0f0f0f
x & 0x0f0f0f0f的結果如下圖所示:
-
(x & 0x0f0f0f0f) << 4
左移四位後結果如下圖所示:
-
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
然後兩個數或運算,結果如下圖所示:
第三行程式碼運算完成。
總結,x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
這行的程式碼就是以8個bit位為一組,分成左邊四個bit位一段和右邊四個bit位一段,然後這兩段相互對調。
圖解就是將下圖
轉換成
分析第四行程式碼:
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
目前x的數值為:
-
0xff00ff00
0xff00ff00是從第0位開始,0和1每隔八位交替出現
0xff00ff00= 0b11111111000000001111111100000000
-
x & 0xff00ff00
x & 0xff00ff00的結果如下圖所示:
-
(x & 0xff00ff00) >> 8
右移八位後結果如下圖所示:
-
0x00ff00ff
0x00ff00ff是從第0位開始,1和0每隔八位交替出現
0x00ff00ff= 0b00000000111111110000000011111111
-
x & 0x00ff00ff
x & 0x00ff00ff的結果如下圖所示:
-
(x & 0x00ff00ff) << 8
左移八位後結果如下圖所示:
-
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
然後兩個數或運算,結果如下圖所示:
第四行程式碼運算完成。
總結,x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
這行的程式碼就是以16個bit位為一組,分成左邊八個bit位一段和右邊八個bit位一段,然後這兩段相互對調。
圖解就是將下圖
轉換成
分析最後一行程式碼:
((x >> 16) | (x << 16))
目前x的數值為:
高16bit與低16bit進行交換,結果如下圖:
完成整個位反轉演算法。
8位數的高效位反轉演算法實現
如果要對8位數進行位反轉,原理相同,程式碼如下:
unsigned char reverse(unsigned char x)
{
x = (((x & 0xaa) >> 1) | ((x & 0x55) << 1));
x = (((x & 0xcc) >> 2) | ((x & 0x33) << 2));
return ((x >> 4) | (x << 4));
}
即可實現對8位數的高效位反轉。
[參考資料]
[Hacker’s Delight] 作者: Henry S. Warren Jr.
The Aggregate Magic Algorithms
相關文章
- 智慧演算法學習筆記(一) (轉)演算法筆記
- MIT 6.824 學習筆記(一)--- RPC 詳解MIT筆記RPC
- Go學習筆記-GMP詳解Go筆記
- 《SQL 反模式》 學習筆記SQL模式筆記
- TensorFlow常量、變數和佔位符詳解(學習筆記)變數筆記
- PE學習筆記(一) (轉)筆記
- git reset 命令詳解(一)—— Git 學習筆記 07Git筆記
- JVM學習筆記(3)---OutOfMemory詳解JVM筆記
- repuest轉發學習筆記一筆記
- C#學習筆記(一) (轉)C#筆記
- Microsoft Agent 學習筆記 (一) (轉)ROS筆記
- Spring---IoC(控制反轉)原理學習筆記【全】Spring筆記
- 堆溢位學習筆記筆記
- 學習筆記:數位dp筆記
- 數位DP 學習筆記筆記
- 【學習筆記】數位DP筆記
- mysql學習筆記-底層原理詳解MySql筆記
- Nginx變數詳解(學習筆記十九)Nginx變數筆記
- 《如何高效學習》讀書筆記筆記
- 演算法學習筆記演算法筆記
- STL的學習筆記之一 (轉)筆記
- git checkout 命令詳解—— Git 學習筆記 16Git筆記
- JavaWeb學習筆記_Day03_JavaScript詳解Web筆記JavaScript
- JMeter學習筆記--詳解JMeter定時器JMeter筆記定時器
- sed學習筆記(轉)筆記
- gurb學習筆記(轉)筆記
- ANT學習筆記 (轉)筆記
- GRUB學習筆記(轉)筆記
- TreeView學習筆記 (轉)View筆記
- 學習筆記(一)筆記
- 資料結構學習筆記(一) (轉)資料結構筆記
- LMF演算法學習筆記演算法筆記
- 機器學習演算法學習筆記機器學習演算法筆記
- 匈牙利演算法學習筆記演算法筆記
- 學習筆記----KM演算法筆記演算法
- 學習筆記----RMQ演算法筆記MQ演算法
- EM演算法學習筆記演算法筆記
- Floyd演算法學習筆記演算法筆記