有谁知道为什么我的 java 代码使用 n=n/2 不能正常工作,而 n>>1 可以?
Does anyone know why my java code doesn't work properly using n=n/2 while n>>1 does?
这是leetcode(https://leetcode.com/problems/number-of-1-bits/)的一道题。
此方法用于计算此数字在二进制中的 1。
我尝试使用 n=n/2 ,它不会通过所有情况,而 n=n>>1 会。有谁知道为什么吗??
public class Numberof1Bits {
public static void main(String[] args) {
System.out.println(new Numberof1Bits()
.hammingWeight(0b11111111111111111111111111111111));
}
public int hammingWeight(int n) {
int count = 0;
if (n < 0)
count++;
for (int i = 0; i < 31; i++) {
if ((n & 1) == 1)
count++;
n = n >> 1;// while this doesn't work when n=n/2;
}
return count;
}
}
您正在使用无符号整数。 0xFFFFFFFF = -1。 -1 >> 1 = -1。 -1/2 = 0。对于设置了最高有效位的任何数字都会失败。
如果 Java,>>
运算符执行符号扩展按位右移。例如(为了清楚起见,我使用 8 位数字):
0b10111111 >> 1 => 0b11011111
十进制相同:
-65 >> 1 => -33
位右移一位,最高位保持原样。我的示例编号 (0b10111111) 是十进制的 -65。如果将其除以二,则得到 -32。是的,我们在翻译中丢失了一点。 /2
执行算术除法,相当于 >> 1
仅 用于正数。
在支持无符号整数和无符号右移的语言中,n/2 应该可以正常工作。
在 java 中,因为 >>
是有符号的,你可以使用 >>>
右移 而没有 符号扩展,并且可能更快的循环:
public int hammingWeight(int n) {
int count = 0;
while(n != 0) {
if ((n & 1) != 0) {
count++;
}
n = n >>> 1;
}
return count;
}
>> 1
将 int
除以二,但舍入是使用 floor 完成的,即向负无穷大舍入。 Java 语言规范中的相关引用:
The value of n >> s is n right-shifted s bit positions with
sign-extension. The resulting value is floor(n / 2^s).
例如,
20 >> 1 == 10
15 >> 1 == 7 (7.5 is rounded down to 7)
-20 >> 1 == -10
-15 >> 1 == -8 (-7.5 is rounded down to -8)
另一方面,对于 /
,四舍五入是朝着零方向进行的。这来自 Java 语言规范:
The binary / operator performs division, producing the quotient of its
operands. The left-hand operand is the dividend and the right-hand
operand is the divisor.
Integer division rounds toward 0.
例如,
20 / 2 == 10
15 / 2 == 7 (7.5 is rounded down to 7)
-20 / 2 == -10
-15 / 2 == -7 (-7.5 is rounded UP to -7)
对于负奇数 n
,n /= 2
因此与 n >>= 1; n++;
相同。 n++
将完全改变设置位数的计算方式。
这是leetcode(https://leetcode.com/problems/number-of-1-bits/)的一道题。 此方法用于计算此数字在二进制中的 1。 我尝试使用 n=n/2 ,它不会通过所有情况,而 n=n>>1 会。有谁知道为什么吗??
public class Numberof1Bits {
public static void main(String[] args) {
System.out.println(new Numberof1Bits()
.hammingWeight(0b11111111111111111111111111111111));
}
public int hammingWeight(int n) {
int count = 0;
if (n < 0)
count++;
for (int i = 0; i < 31; i++) {
if ((n & 1) == 1)
count++;
n = n >> 1;// while this doesn't work when n=n/2;
}
return count;
}
}
您正在使用无符号整数。 0xFFFFFFFF = -1。 -1 >> 1 = -1。 -1/2 = 0。对于设置了最高有效位的任何数字都会失败。
如果 Java,>>
运算符执行符号扩展按位右移。例如(为了清楚起见,我使用 8 位数字):
0b10111111 >> 1 => 0b11011111
十进制相同:
-65 >> 1 => -33
位右移一位,最高位保持原样。我的示例编号 (0b10111111) 是十进制的 -65。如果将其除以二,则得到 -32。是的,我们在翻译中丢失了一点。 /2
执行算术除法,相当于 >> 1
仅 用于正数。
在支持无符号整数和无符号右移的语言中,n/2 应该可以正常工作。
在 java 中,因为 >>
是有符号的,你可以使用 >>>
右移 而没有 符号扩展,并且可能更快的循环:
public int hammingWeight(int n) {
int count = 0;
while(n != 0) {
if ((n & 1) != 0) {
count++;
}
n = n >>> 1;
}
return count;
}
>> 1
将 int
除以二,但舍入是使用 floor 完成的,即向负无穷大舍入。 Java 语言规范中的相关引用:
The value of n >> s is n right-shifted s bit positions with sign-extension. The resulting value is floor(n / 2^s).
例如,
20 >> 1 == 10
15 >> 1 == 7 (7.5 is rounded down to 7)
-20 >> 1 == -10
-15 >> 1 == -8 (-7.5 is rounded down to -8)
另一方面,对于 /
,四舍五入是朝着零方向进行的。这来自 Java 语言规范:
The binary / operator performs division, producing the quotient of its operands. The left-hand operand is the dividend and the right-hand operand is the divisor.
Integer division rounds toward 0.
例如,
20 / 2 == 10
15 / 2 == 7 (7.5 is rounded down to 7)
-20 / 2 == -10
-15 / 2 == -7 (-7.5 is rounded UP to -7)
对于负奇数 n
,n /= 2
因此与 n >>= 1; n++;
相同。 n++
将完全改变设置位数的计算方式。