无符号整数的反转位

时间:2015-09-14 03:16:34

标签: java integer bit-manipulation

以下两个代码是该方法可以反转无符号32位整数的位。但是下面两个代码的区别是什么? 为什么第一个代码是错误的,第二个代码是正确的。 我看不出这两者的区别。

public int reverseBits(int n) {
    int result = 0;
    for (int i = 0; i < 32; i++) {
        result = result << 1 | (n & (1 << i));
    }
    return result;
}
public int reverseBits(int n) {
    int result = 0;
    for (int i = 0; i < 32; i++) {
        result = result << 1 | ((n >> i) & 1);
    }
    return result;
}

感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

它与从n抓取的位是存储在结果的最右位还是存储回相同位置有关。

答案 1 :(得分:0)

假设n为4(例如)。 然后当i为2时,表达式(n & (1 << i)) 变为(4 & (1 << 2)),它应该等于4 & 4,因此它的计算结果为4。 但表达式((n >> i) & 1) 变为((4 >> 2) & 1),它应该等于1 & 1,因此它的计算结果为1.

这两个表达式的结果不一样。

但是该函数的两个版本都试图以完全相同的方式使用这些结果,因此该函数的两个版本没有相同的结果。

答案 2 :(得分:0)

第一个代码是错误的,因为它提取给定位并将其放在结果数字的相同位置。假设您正在进行迭代i = 5。然后n & (1 << 5) = n & 32,其为0或0b100000。目的是将一位置于最低位置,但执行|时操作它实际上把它放到#5的相同位置。在随后的迭代中,您将此位移动得更高,因此您实际上将所有位或位于最高位位置。

请注意,有一些更有效的算法来反转位,就像在标准JDK Integer.reverse方法中实现的那样:

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;
}