Я пытаюсь понять, почему, если я сдвигаю отрицательное целое число -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
Но в случае, когда х равен -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). Таким образом, вы не получаете половин при сдвиге, поскольку дивиденды вынуждены быть четными. Например,
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
,
Он одинаков для всех известных мне языков — битовое арифметическое смещение вправо для -1 будет равно -1, и, как уже упоминалось, эту операцию можно применять только к целым числам.
-1 представлен в двоичном виде как все биты, заполненные значением 1. Для арифметического сдвига вправо биты будут сдвинуты вправо, а старший бит (слева) будет заполнен знак от значения, для отрицательных значений это будет 1, а для положительных — 0. Таким образом, после сдвига он снова будет равен -1.
Существуют другие виды битовых сдвигов, и для логического сдвига вправо старший бит будет заполнен нулем. Вы можете получить больше информации здесь: http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift