Ответы:
>>
арифметический сдвиг вправо, >>>
логический сдвиг вправо.
При арифметическом сдвиге знаковый бит расширяется, чтобы сохранить подпись числа.
Например: -2, представленный в 8 битах, будет 11111110
(потому что старший значащий бит имеет отрицательный вес). Сдвиг вправо на один бит с использованием арифметического сдвига даст вам 11111111
или -1. Логическое смещение вправо, однако, не заботится о том, чтобы значение могло представлять число со знаком; он просто перемещает все вправо и заполняет слева нулями. Сдвиг нашего -2 правильного бита с использованием логического сдвига даст 01111111
.
2^k
, я нахожу странным, что это ответ каждого. Строка битов не является числом и >>
всегда может использоваться с любой строкой битов: она всегда выполняет одно и то же, независимо от роли, которую играет строка битов, и независимо от того, имеет ли она понятие «знак». Было бы хорошо дополнить ваш и без того отличный ответ обсуждением случая, когда ваш операнд не интерпретируется как число со знаком? Имеет ли смысл моя жалоба?
String
также может рассматриваться как a char[]
. Он не говорит, что это char
не число; он просто говорит, что это число без знака . Я думаю, что там он и потерян.
>>>
беззнаковая смена; это вставит 0. >>
подписано, и расширит бит знака.
Операторы сдвига включают сдвиг влево, сдвиг
<<
вправо со знаком>>
и сдвиг вправо без знака>>>
.Значение
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.
1 >>> 32 == 1
Они оба сдвига вправо, но >>>
этоunsigned
Из документации :
Оператор смещения вправо без знака «>>>» смещает ноль в крайнее левое положение, а крайнее левое положение после «>>» зависит от расширения знака.
>>>
это без знака, но почему 7>>32=7
? Я запустил цикл, который делал по одной смене за раз, и увидел, что после 32
смен он вернулся 7
. Единственный способ, которым это может иметь смысл, состоит в том, что для каждого смещенного числа оно входит во «внешний круг». После 32
смены он каким-то образом вернулся к своей позиции, но, очевидно, это все еще не имеет смысла. Что здесь происходит?
Логическое правое смещение ( 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
Когда биты представляют собой число в представлении, дополняющем два, арифметическое смещение вправо имеет эффект деления на степень два. Это работает, потому что самый левый бит является знаковым битом. Деление на степень два должно держать знак одинаковым.
Узнайте больше о побитовых и битовых операторах
>> 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
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0'))
:; Integer.MAX_VALUE : 01111111111111111111111111111111;
Integer.MIN_VALUE : 10000000000000000000000000000000;
-1 : 11111111111111111111111111111111;
0 : 00000000000000000000000000000000;
1 : 00000000000000000000000000000001
Логический оператор сдвига вправо ( >>> N
) сдвигает биты вправо на N позиций, отбрасывая знаковый бит и дополняя N крайних левых битов нулями. Например:
-1 (in 32-bit): 11111111111111111111111111111111
после >>> 1
операции становится:
2147483647: 01111111111111111111111111111111
Арифметический оператор правого сдвига ( >> N
) также сдвигает биты вправо на N позиций, но сохраняет знаковый бит и дополняет N крайних левых бит 1. Например:
-2 (in 32-bit): 11111111111111111111111111111110
после >> 1
операции становится:
-1: 11111111111111111111111111111111