Правильный сдвиг:
Оператор сдвига вправо, >>, сдвигает все биты в значении вправо на указанное число раз.
Общая форма: значение >> число
Здесь num указывает количество позиций для сдвига вправо значения в значении. То есть >> перемещает все биты в указанном значении вправо на количество битовых позиций, указанных в num.
Следующий фрагмент кода сдвигает значение 32 вправо на две позиции, в результате чего устанавливается значение 8:
int a = 32;
a = a >> 2; // a now contains 8
Когда значение имеет биты, которые «сдвинуты», эти биты теряются. Например, следующий фрагмент кода сдвигает значение 35 вправо на две позиции, что приводит к потере двух младших битов, в результате чего снова устанавливается значение 8.
int a = 35;
a = a >> 2; // a still contains 8
Глядя на ту же операцию в двоичном коде, более четко видно, как это происходит:
00100011 35 >> 2
00001000 8
Каждый раз, когда вы сдвигаете значение вправо, оно делит это значение на два и отбрасывает любой остаток. Вы можете воспользоваться этим для высокопроизводительного целочисленного деления на 2. Конечно, вы должны быть уверены, что не сдвинете биты с правого конца.
Когда вы сдвигаетесь вправо, верхние (самые левые) биты, выставленные правым сдвигом, заполняются предыдущим содержимым верхнего бита. Это называется расширением знака и служит для сохранения знака отрицательных чисел при их правильном смещении. Например, –8 >> 1
равно –4
, что в двоичном виде равно
11111000 –8 >>1
11111100 –4
Интересно отметить, что если вы сдвинете вправо –1, результат всегда останется –1, поскольку расширение знака продолжает вводить больше единиц в старших битах.
Иногда нежелательно подписывать значения-расширения, когда вы сдвигаете их вправо. Например, следующая программа преобразует значение байта в его шестнадцатеричное строковое представление. Обратите внимание, что смещенное значение маскируется с помощью AND с 0x0f для отбрасывания любых битов с расширенными знаками, чтобы это значение можно было использовать в качестве индекса в массиве шестнадцатеричных символов.
// Masking sign extension.
class HexByte {
static public void main(String args[]) {
char hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
byte b = (byte) 0xf1;
System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);
}
}
Вот вывод этого:
b = 0xf1