为什么在PHP中右移-1总是得到-1?

7

我正在尝试弄清楚为什么如果我将负整数-1进行移位操作,结果总是得到-1,例如:

echo -1 >> 64; // -1
echo -1 >> 5; // -1
echo -1 >> 43; // -1
echo -1 >> 1; // -1

无论右移的第二个操作数是什么,-1仍然保持为-1... 我理解右移的实际操作如下所示: x >> y = x / 2^y
但是,在x为-1的情况下,如果这样操作: -1 >> 3 = -1 / 2^3
这个值不应该是-1/8=-0.125吗?
感谢关注。

4
整数,整数,整数。 - The Paramagnetic Croissant
1
引用手册(我强调):“位运算符允许在整数中评估和操作特定的位。” - Mark Baker
2
哦,天啊,认真的吗...5个赞?这一定是噩梦! - The Paramagnetic Croissant
2个回答

8

按位移位运算符不进行除法运算,它们会做它们该做的事情——移动比特位。特别是,右移位运算符执行以下操作:

  • 对于从右侧开始的每个比特位,将其值设置为其左侧的值
  • 对于最左侧的比特位,即没有任何左侧内容的比特位,则保留其当前值

例如,如果您的数字是

1011...101

右移操作会得到

11011...10

因此,最右边的位(LSB)会丢失,最左边的位(MSB)会被复制。这被称为“符号传播”,因为MSB用于区分正数(MSB=0)和负数(MSB=1)。
负数以“二进制补码”存储,即在32位系统上,“-x”存储为“2^32-x”。因此,“-1”为“10...00(32个零)-1”==“1...1(32个1)”。如果按照上述过程移位32个1,则结果仍为32个1,即“-1 >> 任何值”始终为“-1”。
右移和除以2的差异在于,对于奇数和偶数,移位都会得到相同的结果。由于最右边的位被丢弃,所以当您移位奇数(具有LSB = 1)时,结果与移位至下一个较低偶数(相同的位组合,但LSB = 0)相同。因此,您不会得到一半的值,因为被除数被强制为偶数。例如,
1010 = 10102,10/2 = 5.0,而10 >> 1 == 510 == 1012 1110 = 10112,11/2 = 5.5,但11 >> 1 == 510 == 1012 如果您更喜欢以除法的方式考虑“x >> 1”,则它首先将x向下舍入为偶数(“x-abs(x)%2”),然后将该数字除以二。
对于“x = -1”,这将为您提供“(-1-abs(-1)%2)/ 2 ==(-1-1)/ 2 = -2/2 = -1”。

3
我所知道的所有语言都是一样的——对于-1的位运算右移结果还是-1。正如其他人所提到的,此操作只能应用于整数。

-1在二进制中表示为所有位均为1。对于算术右移,这些位将被向右移动,并且值的符号将填充在最高位(左侧),对于负数它将是1,而对于正数则是0。因此,在移位后,又变成了-1。

还有其他类型的位移,对于逻辑右移,最高位将被填充为零。您可以在这里获取更多信息:http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift


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