为什么我需要在对结果求和之前左移?

Why do i need to left shift before summing the result?

这是一个按预期工作的代码片段,它正确地反转了整数的位和 returns 新的 int。我的问题是为什么 result <<= 1 行必须出现在我用操作 n&1?

求和结果之前

在第一次迭代中,它不会影响结果,因为结果被实例化为 0。如果我将 result <<= 1 行放在 for 循环的末尾,我仍然会在我之前移动结果将结果与 n&1 相加。 我的代码(最后是左移结果)无法正常工作,我似乎无法理解这最后一步。

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

因为否则你操作错误的位。请注意,如果有帮助,您可以用简单的算术和除法替换当前的移位。喜欢,

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

解释1:

result <<= 1;

等同于result = result * 2,与result = result + result相同,可以结合下一条指令;

result += n&1

并得到

result += result + (n & 1);

至于>>= 1,与/ 2相同。

1数学.

在第一次迭代中它确实没有效果,但没关系,这是故意的。它比写 if (i != 0) result <<= 1; 更好。在每次迭代中检查它是低效的。但同样重要的是要注意这一点,基本上在 32 次迭代中,只有在 31 次迭代中它才会有效果并且应该。因此,如果您将 result <<= 1; 行放在末尾,则要确保它仅有效执行 31 次,同时请记住,现在它应该在顺序更改后的第一次迭代中执行,但不应在最后一次迭代中执行迭代。这就是结果无效的原因。

试试这个。这会起作用。

public int reverseBits(int n) {
    int result = 0;
    for(int i=0; i<32; i++){
        result += n&1;
        n >>= 1;
        if (i != 31) // skip the shift in last iteration
            result <<= 1;
    }
    return result;
}

这是一个一次性问题:

  • 你需要复制 32 位,所以你要执行 32 result += n&1; 操作 (0..31)
  • 要将最右边的位(位置0)移动到最左边的位置(位置31)只需要进行31次左移操作。

因此,将 result <<= 1; 放在开头是可以的,因为它实际上什么也不做,因为 result 中还没有任何内容,所以您只进行了 31 次左移。 仅当您在 result += n&1; 之后移动它时,您才进行 32 次左移操作,丢失一位。 n >>= 1; 也是如此,您也执行 32 次右移操作,但最后的右移并不重要,因为它永远不会添加到结果中(无论如何都是零)。