Что уменьшается по модулю 32 или 64? - PullRequest
2 голосов
/ 02 февраля 2012

В книге Core Java Volume1 есть предостережение:

ВНИМАНИЕ: правый аргумент операторов сдвига уменьшается по модулю 32 (если левая сторона не длинная, в этом случае правая сторона уменьшается по модулю 64). Например, значение 1 << 35 совпадает с 1 << 3 или 8. </p>

Что именно это значит? и почему 1 становится 8, а не 0 после 35 смещения влево?

большое спасибо

Ответы [ 3 ]

10 голосов
/ 02 февраля 2012

Уменьшение по модулю 32 означает (на базовом уровне), что вы продолжаете вычитать 32, пока не получите число от 0 до 31 включительно.

Другими словами:

actualValue = givenValue % 32;

Причина заключается в том, что нет смысла сдвигать 32-битное значение на 32 бита влево (или вправо), поскольку всегда будет нулевым (поскольку вы сдвигаете биты с одной стороны и смещаете нули в с другой стороны - выполнение этого 32 раза до 32-битного значения приведет к нулю независимо от того, с чего вы начали).

Таким образом, для целых чисел Java (32-разрядных) 31 является разумным пределом. Для длинных (64-битных) разумным пределом является 63.

В приведенном вами примере значение 1 << 35 уменьшено с 35 до 3 (начиная с 35 % 32 == 3), а 1 << 3 равно 8: </p>

 Binary
0000 0001    (1 << 0) == 1
0000 0010    (1 << 1) == 2
0000 0100    (1 << 2) == 4
0000 1000    (1 << 3) == 8
     ||||
     |||+--- 1
     ||+---- 2
     |+----- 4
     +------ 8
5 голосов
/ 02 февраля 2012

Во многих языках программирования смещение более чем на размер числового типа данных (32 бита для целого, 64 бита для длинного) не определено. С другой стороны, Java определяет его так, что (n << d) эквивалентно (n << (d % 32)), где n является целым числом, а (n << d) эквивалентно (n << (d % 64)), где n является длинным.

Итак, 1 << 35 эквивалентно 1 << (35 % 32), что равно 1 << 3 = 8.

4 голосов
/ 02 февраля 2012

Более кратко

a << b

совпадает с

a << (b & 31)

для типов int.

Разница в том, что -1% 32 равно -1, тогда как -1 и 31 равен 31 и 1 << -1 == 0x80000000

Это поведение определено в JLS 15.19

Если тип левого операнда с расширенным типом - int,только пять младших битов правого операнда используются в качестве расстояния сдвига.Это как если бы правый операнд был обработан побитовым логическим оператором И & (§15.22.1) со значением маски 0x1f (0b11111).Следовательно, фактически используемое расстояние сдвига всегда находится в диапазоне от 0 до 31 включительно.

Если тип левого операнда с продвинутым типом является длинным, то только шесть младших битов правого операндаиспользуются в качестве расстояния сдвига.Это как если бы правый операнд был обработан побитовым логическим оператором И & (§15.22.1) со значением маски 0x3f (0b111111).Поэтому фактически используемое расстояние смещения всегда находится в диапазоне от 0 до 63 включительно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...