Why does right shifting -1 always gives -1 in PHP?

杀马特。学长 韩版系。学妹 提交于 2019-12-22 05:33:33

问题


I am trying to figure out why if I shift the negative integer -1 I always get -1, e.g.:

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

Whatever second operand of the right shift is given, -1 remains -1... I do understand that when you perform a right shift you're actually doing this:

x >> y = x / 2^y

But in the case of x being -1, if so, I do:

-1 >> 3 = -1 / 2^3

Shouldn't this value be -1/8 = -0.125?

Thanks for the attention.


回答1:


Bitwise shift operators don't divide. They do what they are supposed to do - shift bits. In particular, the right shift operator does the following:

  • for each bit starting from the right, set its value to what's on the left of it
  • for the leftmost bit, which has nothing on the left, keep its current value

For example, if your number is

1011...101

right shift gives you

11011...10

So the rightmost bit (LSB) is lost and the leftmost bit (MSB) is duplicated. This is called "sign propagation", because MSB is used to distinguish positive (MSB=0) from negative (MSB=1) numbers.

Negative numbers are stored as "two's complement", that is, on a 32-bit system, -x is stored as 2^32-x. So, -1 is 10...00 (32 zeroes) - 1 == 1...1 (32 ones). If you shift 32 ones according to the above procedure, you get 32 ones yet again, that is, -1 >> whatever will always be -1.

The difference between the right shift and division by two is that the shift gives same results for odd and even numbers. Since the rightmost bit is lost, when you shift an odd number (which has LSB=1), the result is the same as shifting the next lower even number (the same combination of bits, but with LSB=0). So, you get no halves when you shift, since the dividend is forced to be even. For example,

1010 = 10102, 10 / 2 = 5.0 and 10 >> 1 == 510 == 1012

1110 = 10112, 11 / 2 = 5.5 but 11 >> 1 == 510 == 1012

If you prefer to think about x >> 1 in terms of division, it first "rounds" x down to an even number (x - abs(x) % 2) and then divides that number by two.

For x = -1 this gives you (-1 - abs(-1) % 2)/2 == (-1 - 1)/2 = -2/2 = -1.




回答2:


It is the same in all languages I know - bitwise arithmetic right shift for -1 will be -1, and as others mentioned, this operation can be applied only to integers.

-1 is represented in binary as all bits filled with value 1. For arithmetic right shift the bits will be shifted to the right, and the highest bit (at the left) will be filled with sign of the value, for negative values it will be 1, and for positive - 0. So it makes -1 again after the shift.

There are other kinds of bitwise shifts, and for logical right shift the highest bit would be filled with zero. You can get some more info here: http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift



来源:https://stackoverflow.com/questions/26821728/why-does-right-shifting-1-always-gives-1-in-php

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!