Я пытаюсь понять, почему, если я смещаю отрицательное целое число -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?
Спасибо за внимание.
Операторы побитового сдвига не делятся. Они делают то, что они должны делать, – сдвигают биты. В частности, оператор правого сдвига выполняет следующее:
Например, если ваш номер
1011...101
правая смена дает вам
11011...10
Таким образом, самый правый бит (LSB) теряется, а самый левый бит (MSB) дублируется. Это называется «распространение знака», поскольку MSB используется для выделения положительных (MSB = 0) из отрицательных (MSB = 1) чисел.
Отрицательные числа хранятся как «дополнение двух», то есть в 32-битной системе, -x
хранится как 2^32-x
. Итак, -1
– 10...00 (32 zeroes) - 1
== 1...1 (32 ones)
. Если вы переместите 32 в соответствии с приведенной выше процедурой, вы снова получите 32, то есть -1 >> whatever
что всегда будет -1
.
Разница между правым сдвигом и делением на два состоит в том, что сдвиг дает одинаковые результаты для нечетных и четных чисел. Так как самый правый бит потерян, когда вы смещаете нечетное число (которое имеет LSB = 1), результат будет таким же, как сдвиг следующего нижнего четного числа (одна и та же комбинация бит, но с LSB = 0). Таким образом, вы не получаете половинок при смене, так как дивиденд вынужден быть четным. Например,
10 10 = 1010 2 , 10/2 = 5,0 и 10 >> 1 == 5 10 == 101 2
11 10 = 1011 2 , 11/2 = 5,5, но 11 >> 1 == 5 10 == 101 2
Если вы предпочитаете думать о x >> 1
в терминах деления, он сначала «округляет» x до четного числа ( x - abs(x) % 2
), а затем делит это число на два.
При x = -1
это дает вам (-1 - abs(-1) % 2)/2 == (-1 - 1)/2 = -2/2 = -1
.
Это то же самое на всех языках, которые я знаю – побитовый арифметический сдвиг вправо для -1 будет равным -1, и, как упоминалось выше, эту операцию можно применять только к целым числам.
-1 представляется в двоичном виде, поскольку все биты, заполненные значением 1. Для арифметического сдвига вправо биты будут сдвинуты вправо, а старший бит (слева) будет заполнен знаком значения, для отрицательных значений он будет 1, а для положительного – 0. Таким образом, после сдвига он снова становится -1.
Существуют и другие виды поразрядных сдвигов, а для логического сдвига вправо старший бит заполняется нулем. Вы можете получить дополнительную информацию здесь: http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift