负整数的位移操作?

8

我正在尝试理解对负整数进行的位移操作 >>

-2 >> 1 # -1
-3 >> 1 # -2
-5 >> 1 # -3
-7 >> 1 # -4

有人能解释一下这是如何完成的吗?我知道它与二进制补码相关,但我不知道如何将其与移位操作联系起来。


它正在扩展符号位,因此结果仍然为负数。 - martineau
1个回答

9
完整的解释可以在这里找到。
负整数的二进制补码: 负数使用前导1而不是前导0进行编写。因此,如果您仅使用8位进行补码数字,则将模式从“00000000”到“01111111”视为从0到127的整数,并保留“1xxxxxxx”以编写负数。使用(x-1)的比特模式编写负数-x,并且所有位都被补码(从1切换到0或从0切换到1)。因此,-1是complement(1-1)= complement(0)=“11111111”,-10是complement(10-1)= complement(9)= complement(“00001001”)=“11110110”。这意味着负数一直下降到-128(“10000000”)。
当然,Python不使用8位数字。它曾经使用本机于您的计算机的位数,但由于这是不可移植的,因此最近已经切换到使用无限数量的位。因此,按位运算符处理数字-5,就好像它是写成“... 1111111111111111111011”。
因此,移位运算符的解释如下: x >> y将x向右移y位。这与//'ing x by 2 ** y相同。
为了理解上述解释,您可以尝试使用类似以下内容的内容:
def twos_comp(val, nbits):
    """Compute the 2's complement of int value val"""
    if val < 0:
        val = (1 << nbits) + val
    else:
        if (val & (1 << (nbits - 1))) != 0:
            # If sign bit is set.
            # compute negative value.
            val = val - (1 << nbits)
    return val

def foo(a,b):
    print("{0:b} >> {1:b} = {2:b} <==> {3:b} >> {4:b} = {5:b}".format(
        a,b,a>>b,
        twos_comp(a,8),b, twos_comp(a>>b,8)
    ))

foo(-2, 1)
foo(-3, 1)
foo(-5, 1)
foo(-7, 1)

这会产生以下输出:

-10 >> 1 = -1 <==> 11111110 >> 1 = 11111111
-11 >> 1 = -10 <==> 11111101 >> 1 = 11111110
-101 >> 1 = -11 <==> 11111011 >> 1 = 11111101
-111 >> 1 = -100 <==> 11111001 >> 1 = 11111100

如您所见,数字的二进制补码将扩展符号位。


你好,对于负整数的二进制右移操作,这是如何工作的呢? - spundian
1
@spundian:在答案中已经详细解释了。 - pts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接