有谁知道为什么我的 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;
}

>> 1int 除以二,但舍入是使用 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)

对于负奇数 nn /= 2 因此与 n >>= 1; n++; 相同。 n++ 将完全改变设置位数的计算方式。