Логический сдвиг вправо (v >>> n
) возвращает значение, в котором биты в v
сдвинуты вправо на n
битовые позиции, а 0 сдвинуты с левой стороны. Рассмотрим смещение 8-битных значений, записанных в двоичном виде:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
Если мы интерпретируем биты как неотрицательное целое число без знака, логический сдвиг вправо приводит к делению числа на соответствующую степень 2. Однако, если число находится в представлении, дополняющем два, логическое сдвиг вправо не будет разделить отрицательные числа. Например, второй правый сдвиг выше сдвигает от 128 до 32, когда биты интерпретируются как числа без знака. Но он сдвигается от -128 до 32, когда, как это обычно бывает в Java, биты интерпретируются как дополнение к двум.
Поэтому, если вы сдвигаетесь, чтобы делить на степень два, вам нужно арифметическое смещение вправо (v >> n
). Он возвращает значение, при котором биты в v
были сдвинуты вправо на n
битовые позиции, а копии самого левого бита v сдвинуты с левой стороны:
01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
Когда биты представляют собой число в представлении, дополняющем два, арифметическое смещение вправо приводит к делению на степень два. Это работает, потому что самый левый бит является битом знака. Деление на степень два должно держать знак одинаковым.