shift — Почему смещение вправо -1 всегда дает -1 в PHP?

Я пытаюсь понять, почему, если я сдвигаю отрицательное целое число -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?

Спасибо за внимание.

6

Решение

Битовые операторы сдвига не делятся. Они делают то, что должны — сдвигать биты. В частности, оператор сдвига вправо делает следующее:

  • для каждого бита, начинающегося справа, установите его значение на то, что слева от него
  • для самого левого бита, который не имеет ничего слева, сохраните его текущее значение

Например, если ваш номер

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,

7

Другие решения

Он одинаков для всех известных мне языков — битовое арифметическое смещение вправо для -1 будет равно -1, и, как уже упоминалось, эту операцию можно применять только к целым числам.

-1 представлен в двоичном виде как все биты, заполненные значением 1. Для арифметического сдвига вправо биты будут сдвинуты вправо, а старший бит (слева) будет заполнен знак от значения, для отрицательных значений это будет 1, а для положительных — 0. Таким образом, после сдвига он снова будет равен -1.

Существуют другие виды битовых сдвигов, и для логического сдвига вправо старший бит будет заполнен нулем. Вы можете получить больше информации здесь: http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift

2

По вопросам рекламы [email protected]