前几天在写道进制翻转的题目,发现JAVA提供了直接调用的方法
Integer.reverse(int i)
:二进制按位反转
很好奇点进去发现,源码如下:
/**
* Returns the value obtained by reversing the order of the bits in the
* two's complement binary representation of the specified {@code int}
* value.
*
* @param i the value to be reversed
* @return the value obtained by reversing order of the bits in the
* specified {@code int} value.
* @since 1.5
*/
public static int reverse(int i) {
// HD, Figure 7-1
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}
这是什么神仙代码?一眼看过去丈二和尚摸不着头脑。
仔细推敲后发现:
不妨设iii的二进制如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b1b_{1}b1 | b2b_{2}b2 | b3b_{3}b3 | b4b_{4}b4 | b5b_{5}b5 | b6b_{6}b6 | b7b_{7}b7 | b8b_{8}b8 | b9b_{9}b9 | b10b_{10}b10 | b11b_{11}b11 | b12b_{12}b12 | b13b_{13}b13 | b14b_{14}b14 | b15b_{15}b15 | b16b_{16}b16 | b17b_{17}b17 | b18b_{18}b18 | b19b_{19}b19 | b20b_{20}b20 | b21b_{21}b21 | b22b_{22}b22 | b23b_{23}b23 | b24b_{24}b24 | b25b_{25}b25 | b26b_{26}b26 | b27b_{27}b27 | b28b_{28}b28 | b29b_{29}b29 | b30b_{30}b30 | b31b_{31}b31 | b32b_{32}b32 |
0x55555555
二进制:0101 0101 0101 0101 0101 0101 0101 0101
所以很容易发现:
(i & 0x55555555) << 1
的结果是:取出iii的偶数位(左移末尾补0),结果如下:记为i1i_1i1
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b2b_{2}b2 | 0 | b4b_{4}b4 | 0 | b6b_{6}b6 | 0 | b8b_{8}b8 | 0 | b10b_{10}b10 | 0 | b12b_{12}b12 | 0 | b14b_{14}b14 | 0 | b16b_{16}b16 | 0 | b18b_{18}b18 | 0 | b20b_{20}b20 | 0 | b22b_{22}b22 | 0 | b24b_{24}b24 | 0 | b26b_{26}b26 | 0 | b28b_{28}b28 | 0 | b30b_{30}b30 | 0 | b32b_{32}b32 | 0 |
(i >>> 1) & 0x55555555
的结果是:取出iii的奇数为(无符号左移首位补0),结果如下:记为i2i_2i2
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | b1b_{1}b1 | 0 | b3b_{3}b3 | 0 | b5b_{5}b5 | 0 | b7b_{7}b7 | 0 | b9b_{9}b9 | 0 | b11b_{11}b11 | 0 | b13b_{13}b13 | 0 | b15b_{15}b15 | 0 | b17b_{17}b17 | 0 | b19b_{19}b19 | 0 | b21b_{21}b21 | 0 | b23b_{23}b23 | 0 | b25b_{25}b25 | 0 | b27b_{27}b27 | 0 | b29b_{29}b29 | 0 | b31b_{31}b31 |
再将i1i_1i1、记为i2i_2i2按位取或运算,结果如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b2b_{2}b2 | b1b_{1}b1 | b4b_{4}b4 | b3b_{3}b3 | b6b_{6}b6 | b5b_{5}b5 | b8b_{8}b8 | b7b_{7}b7 | b10b_{10}b10 | b9b_{9}b9 | b12b_{12}b12 | b11b_{11}b11 | b14b_{14}b14 | b13b_{13}b13 | b16b_{16}b16 | b15b_{15}b15 | b18b_{18}b18 | b17b_{17}b17 | b20b_{20}b20 | b19b_{19}b19 | b22b_{22}b22 | b21b_{21}b21 | b24b_{24}b24 | b23b_{23}b23 | b26b_{26}b26 | b25b_{25}b25 | b28b_{28}b28 | b27b_{27}b27 | b30b_{30}b30 | b29b_{29}b29 | b32b_{32}b32 | b31b_{31}b31 |
可以看出i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
的作用便是将iii中的每两个相邻位交换位置
同理:
0x33333333
二进制:0011 0011 0011 0011 0011 0011 0011 0011
所以应当是每四位中的相邻两位交换,结果如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b4b_{4}b4 | b3b_{3}b3 | b2b_{2}b2 | b1b_{1}b1 | b8b_{8}b8 | b7b_{7}b7 | b6b_{6}b6 | b5b_{5}b5 | b12b_{12}b12 | b11b_{11}b11 | b10b_{10}b10 | b9b_{9}b9 | b16b_{16}b16 | b15b_{15}b15 | b14b_{14}b14 | b13b_{13}b13 | b20b_{20}b20 | b19b_{19}b19 | b18b_{18}b18 | b17b_{17}b17 | b24b_{24}b24 | b23b_{23}b23 | b22b_{22}b22 | b21b_{21}b21 | b28b_{28}b28 | b27b_{27}b27 | b26b_{26}b26 | b25b_{25}b25 | b32b_{32}b32 | b31b_{31}b31 | b30b_{30}b30 | b29b_{29}b29 |
0x0f0f0f0f
二进制:0000 1111 0000 1111 0000 1111 0000 1111
所以应当是每 八位中的相邻四位交换,结果如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b8b_{8}b8 | b7b_{7}b7 | b6b_{6}b6 | b5b_{5}b5 | b4b_{4}b4 | b3b_{3}b3 | b2b_{2}b2 | b1b_{1}b1 | b16b_{16}b16 | b15b_{15}b15 | b14b_{14}b14 | b13b_{13}b13 | b12b_{12}b12 | b11b_{11}b11 | b10b_{10}b10 | b9b_{9}b9 | b24b_{24}b24 | b23b_{23}b23 | b22b_{22}b22 | b21b_{21}b21 | b20b_{20}b20 | b19b_{19}b19 | b18b_{18}b18 | b17b_{17}b17 | b32b_{32}b32 | b31b_{31}b31 | b30b_{30}b30 | b29b_{29}b29 | b28b_{28}b28 | b27b_{27}b27 | b26b_{26}b26 | b25b_{25}b25 |
到最后一步:
i = (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24);
注意:0xff00
实际上是0x0000ff00
(i << 24)
结果:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b32b_{32}b32 | b31b_{31}b31 | b30b_{30}b30 | b29b_{29}b29 | b28b_{28}b28 | b27b_{27}b27 | b26b_{26}b26 | b25b_{25}b25 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
(i & 0xff00) << 8
结果:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | b24b_{24}b24 | b23b_{23}b23 | b22b_{22}b22 | b21b_{21}b21 | b20b_{20}b20 | b19b_{19}b19 | b18b_{18}b18 | b17b_{17}b17 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
(i >>> 8) & 0xff00
结果:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | b16b_{16}b16 | b15b_{15}b15 | b14b_{14}b14 | b13b_{13}b13 | b12b_{12}b12 | b11b_{11}b11 | b10b_{10}b10 | b9b_{9}b9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
(i >>> 24)
结果:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | b8b_{8}b8 | b7b_{7}b7 | b6b_{6}b6 | b5b_{5}b5 | b4b_{4}b4 | b3b_{3}b3 | b2b_{2}b2 | b1b_{1}b1 |
然后在取或运算,得到最后的翻转结果:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b32b_{32}b32 | b31b_{31}b31 | b30b_{30}b30 | b29b_{29}b29 | b28b_{28}b28 | b27b_{27}b27 | b26b_{26}b26 | b25b_{25}b25 | b24b_{24}b24 | b23b_{23}b23 | b22b_{22}b22 | b21b_{21}b21 | b20b_{20}b20 | b19b_{19}b19 | b18b_{18}b18 | b17b_{17}b17 | b16b_{16}b16 | b15b_{15}b15 | b14b_{14}b14 | b13b_{13}b13 | b12b_{12}b12 | b11b_{11}b11 | b10b_{10}b10 | b9b_{9}b9 | b8b_{8}b8 | b7b_{7}b7 | b6b_{6}b6 | b5b_{5}b5 | b4b_{4}b4 | b3b_{3}b3 | b2b_{2}b2 | b1b_{1}b1 |
太神奇了!!!