反转无符号整数的位
Reverse bits of a unsigned integer
下面两段代码是将一个无符号的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;
}
感谢任何帮助。
这与从n中抓取的位是存储在结果的最右位还是存储回相同位置有关。
假设n
为4(举例)。
那么当i
为2时,表达式(n & (1 << i))
变为 (4 & (1 << 2))
,它应该等于 4 & 4
,因此它的计算结果为 4。
但是表达式 ((n >> i) & 1)
变为 ((4 >> 2) & 1)
,它应该等于 1 & 1
,因此它的计算结果为 1。
两个表达式没有相同的结果。
但是函数的两个版本都尝试以完全相同的方式使用这些结果,因此函数的两个版本没有相同的结果。
第一个代码是错误的,因为它提取给定的位并将其放在与结果数相同的位置。假设您正在进行迭代 i = 5
。然后 n & (1 << 5)
= n & 32
即 0 或 0b100000
。本意是将一位放到最低位置,但是在执行|的时候操作它实际上把它放在相同的位置#5。在随后的迭代中,您将此位移得更高,因此实际上所有位都在最高位位置 or'ed。
请注意,有更有效的算法来反转位,例如在标准 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;
}
下面两段代码是将一个无符号的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;
}
感谢任何帮助。
这与从n中抓取的位是存储在结果的最右位还是存储回相同位置有关。
假设n
为4(举例)。
那么当i
为2时,表达式(n & (1 << i))
变为 (4 & (1 << 2))
,它应该等于 4 & 4
,因此它的计算结果为 4。
但是表达式 ((n >> i) & 1)
变为 ((4 >> 2) & 1)
,它应该等于 1 & 1
,因此它的计算结果为 1。
两个表达式没有相同的结果。
但是函数的两个版本都尝试以完全相同的方式使用这些结果,因此函数的两个版本没有相同的结果。
第一个代码是错误的,因为它提取给定的位并将其放在与结果数相同的位置。假设您正在进行迭代 i = 5
。然后 n & (1 << 5)
= n & 32
即 0 或 0b100000
。本意是将一位放到最低位置,但是在执行|的时候操作它实际上把它放在相同的位置#5。在随后的迭代中,您将此位移得更高,因此实际上所有位都在最高位位置 or'ed。
请注意,有更有效的算法来反转位,例如在标准 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;
}