Разница между >>> и >> - PullRequest
       12

Разница между >>> и >>

337 голосов
/ 11 мая 2010

В чем разница между >>> и >> операторами в Java?

Ответы [ 7 ]

368 голосов
/ 11 мая 2010

>> - арифметический сдвиг вправо, >>> - логический сдвиг вправо.

При арифметическом сдвиге бит знака расширяется, чтобы сохранить подпись числа.

Например: -2, представленное в 8 битах, будет 11111110 (потому что старший значащий бит имеет отрицательный вес). Сдвиг вправо на один бит с использованием арифметического сдвига даст вам 11111111 или -1. Логическое смещение вправо, однако, не заботится о том, чтобы значение могло представлять число со знаком; он просто перемещает все вправо и заполняет слева нулями. Сдвиг нашего -2 правильного бита с использованием логического сдвига даст 01111111.

92 голосов
/ 11 мая 2010

>>> - беззнаковая смена; он вставит 0. >> со знаком и расширит бит знака.

JLS 15.19 Операторы сдвига

Операции сдвига включают сдвиг влево <<, сдвиг вправо со знаком >> и сдвиг вправо без знака >>>.

Значение n>>s равно n смещенным вправо s положениям бита с расширением знака .

Значение n>>>s равно n смещенным вправо s битовым позициям с расширением нуля .

    System.out.println(Integer.toBinaryString(-1));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >> 16));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >>> 16));
    // prints "1111111111111111"

Чтобы было понятнее, добавив положительный аналог

System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"

Поскольку положительные сдвиги как со знаком, так и со знаком, без знака добавят 0 к самому левому биту.

Похожие вопросы

46 голосов
/ 11 мая 2010

Они оба смещены вправо, но >>> равно unsigned

Из документации :

Оператор сдвига без знака «>>>» смещает ноль в крайнее левое положение, а крайнее левое положение после «>>» зависит от расширения знака.

38 голосов
/ 11 мая 2010

>>> всегда будет помещать 0 в самый левый бит, в то время как >> будет ставить 1 или 0 в зависимости от того, что это за знак.

36 голосов
/ 26 февраля 2016

Логический сдвиг вправо (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

Когда биты представляют собой число в представлении, дополняющем два, арифметическое смещение вправо приводит к делению на степень два. Это работает, потому что самый левый бит является битом знака. Деление на степень два должно держать знак одинаковым.

9 голосов
/ 30 июля 2014

Подробнее о Операции побитового и битового сдвига

>>      Signed right shift
>>>     Unsigned right shift

Битовая комбинация задается левым операндом, а число позиций для смещения - правым операндом. Оператор смещения вправо без знака >>> переводит ноль в крайнее левое положение ,

, а крайняя левая позиция после >> зависит от расширения знака.

Простыми словами >>> всегда смещает ноль в крайнее левое положение , тогда как >> смещается на основе знака числа, т.е. 1 для отрицательного числа и 0 для положительного числа .


Например, попробуйте как отрицательные, так и положительные числа.

int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));

System.out.println();

c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));

выход:

11111111111111111111111111011001
11111111111111111111111101100100
  111111111111111111111111011001
11111111111111111111111101100100

                          100110
                        10011000
                          100110
                        10011000
5 голосов
/ 27 января 2015

Логический оператор правого сдвига (>>> N) сдвигает биты вправо на N позиций, отбрасывая знаковый бит и дополняя самые левые биты нулями.Например:

-1 (in 32-bit): 11111111111111111111111111111111

после операции >>> 1 становится:

2147483647: 01111111111111111111111111111111

Арифметический оператор правого сдвига (>> N) также сдвигает биты вправо на N позиций, носохраняет бит знака и дополняет N крайних левых бит 1.Например:

-2 (in 32-bit): 11111111111111111111111111111110

после операции >> 1 становится:

-1: 11111111111111111111111111111111
...