问题
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