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

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

Ответ 1

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

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

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

Ответ 2

>>> - беззнаковый сдвиг; он вставляет 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 к самому большому биту.

Связанные вопросы

Ответ 3

Они оба сдвинуты вправо, но >>> есть unsigned

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

Беззнаковый оператор сдвига вправо " → > " сдвигает нуль в крайнее левое положение, а крайняя левая позиция после " → " зависит от расширения знака.

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

>>      Signed right shift
>>>     Unsigned right shift

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

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

В простых словах >>> всегда сдвигает ноль в крайнее левое положение, тогда как >> сдвигается на основе знака числа i.e. 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

Ответ 7

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

-1 (in 32-bit): 11111111111111111111111111111111

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

2147483647: 01111111111111111111111111111111

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

-2 (in 32-bit): 11111111111111111111111111111110

после операции >> 1:

-1: 11111111111111111111111111111111