Каково назначение оператора беззнакового сдвига вправо ">>>" в Java?

Я понимаю, что делает оператор беззнакового сдвига вправо ">>>" в Java, но зачем он нам нужен и почему нам не нужен соответствующий оператор беззнакового сдвига влево?

Комментарии к вопросу (1)
Решение

Оператор >>> позволяет рассматривать int и long как 32- и 64-битные беззназнаковые интегральные типы, которые отсутствуют в языке Java.

Это полезно, когда вы смещаете что-то, что не представляет собой числовое значение. Например, вы можете представить черно-белое изображение битовой карты с помощью 32-битных int, где каждый int кодирует 32 пикселя на экране. Если вам нужно прокрутить изображение вправо, вы предпочтете, чтобы биты слева от int стали нулями, чтобы вы могли легко поместить биты из соседних int:


 int shiftBy = 3;
 int[] imageRow = ...
 int shiftCarry = 0;
 // The last shiftBy bits are set to 1, the remaining ones are zero
 int mask = (1 >> shiftBy) | (carry >>` делает их

Соответствующего оператора `
Комментарии (2)

`>>> и в безопасный и эффективный способ нахождения округлые имею в виду двух (больших) целых чисел:

int mid = (low + high) >>> 1;

Если чисел высокий и низкий близко к крупнейшей машина число, тем выше будут правильными, но

int mid = (low + high) / 2;

можно получить неверный результат из-за переполнения.

Здесь'ы пример использования, исправление ошибки в наивный двоичный поиск.

Комментарии (2)

В основном это связано со знаковыми (числовые сдвиги) или беззнаковыми сдвигами (обычно связанные с пикселями).

Поскольку сдвиг влево не имеет дела с битом знака, это одно и то же ( Как вы только что видели, оператор >> автоматически заполняет

старший бит своим предыдущим содержимым каждый раз, когда происходит сдвиг. Это сохраняет знак значения. Однако иногда это нежелательно. Например, если вы сдвигаете что-то, что не > представляет собой числовое значение. представляет собой числовое значение, то расширение знака может не понадобиться. место. Такая ситуация часто встречается при работе с пиксельными > значениями и графикой. значениями и графикой. В таких случаях обычно требуется сдвинуть ноль в старший бит, независимо от того, каким было его начальное значение. Это известно как беззнаковый сдвиг. Чтобы выполнить это, вы используете беззнаковый оператор java, сдвиг вправо, >>>, который всегда сдвигает нули в старший бит.

Дополнительное чтение:

http://henkelmann.eu/2011/02/01/java_the_unsigned_right_shift_operator

http://www.java-samples.com/showtutorial.php?tutorialid=60

Комментарии (4)

Подписанный оператор сдвига вправо полезно, если есть инт, который представляет номер и хочет разделить его на два, округление в сторону минус бесконечности. Это может быть приятно, когда делаешь такие вещи, как масштабирование координаты отображения; это не только быстрее, чем деление, но координаты которых отличаются на коэффициент масштабирования до масштабирования будет отличаться на один пиксель позже. Если вместо того, чтобы использовать сменную использует деление, что выиграл'т работу. При масштабировании с коэффициентом два, например, -1 и +1 отличаются на две, и таким образом должны опосля отличаться по отдельности, а -1/2=0 и 1/2=0. Если вместо этого используется подпись сдвига вправо, все получается хорошо: -1>>1=1 и 1>>1=0, правильно уступая значений одного пикселя отдельно.

Беззнаковый оператор полезен в случаях, когда входные ожидается ровно один бит и один результат сделать то же самое, или в тех случаях, когда одна будет через цикл, чтобы вывести все биты в слове и хочет его расторгнуть чисто. Например:

void processBitsLsbFirst(int n, BitProcessor whatever)
{
  while(n != 0)
  {
    whatever.processBit(n & 1);
    n >>>= 1;
  }
}

Если код был подписанный правой смену и принял отрицательное значение, это выход 1'ы на неопределенный срок. С unsigned-оператор сдвига вправо, однако, наиболее существенная часть заканчивается интерпретируется просто как и любой другой.

Беззнаковый сдвиг вправо оператор может также оказаться полезной при расчете бы, арифметически, дают положительное число от 0 до 4 294 967 295 и хочет разделить это число на степень двойки. Например, при вычислении суммы двух инт ценности, которые, как известно, будет положительным, можно использовать (П1+П2)>>>1 без содействия операнды "долго". Также, если кто-то хочет разделить положительные типа int значение что-то вроде Пи без использования операций с плавающей точкой, можно вычислить ((значение*5468522205L) >>> 34) [(1л<<34)/Пи 5468522204.61, которые сгоняют дает 5468522205]. На выплату дивидендов за 1686629712, расчет стоимости*5468522205L бы дать на "негативный" и значение, но, поскольку арифметически-правильное значение считается позитивным, используя беззнаковый сдвиг вправо позволит правильное положительное число, чтобы быть использованы.

Комментарии (0)

При обычном сдвиге вправо >> отрицательного числа оно останется отрицательным. То есть бит знака будет сохранен.

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

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

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

Для положительных чисел они действуют одинаково.

Пример использования и >>, и >>> приведен в BigInteger shiftRight.

Комментарии (2)

В Java наиболее типичные применения домена, чтобы избежать переполнения заключается в использовании литья или большое число, например, int в Long и в предыдущих примерах.

int hiint = 2147483647;
System.out.println("mean hiint+hiint/2 = " + ( (((long)hiint+(long)hiint)))/2);
System.out.println("mean hiint*2/2 = " + ( (((long)hiint*(long)2)))/2);

BigInteger bhiint = BigInteger.valueOf(2147483647);
System.out.println("mean bhiint+bhiint/2 = " + (bhiint.add(bhiint).divide(BigInteger.valueOf(2))));
Комментарии (0)