Как работают операторы сдвига в Java?
Я пытаюсь понять операторов смены и не могу получить много. Когда я попытался выполнить приведенный ниже код
System.out.println(Integer.toBinaryString(2 << 11));
System.out.println(Integer.toBinaryString(2 << 22));
System.out.println(Integer.toBinaryString(2 << 33));
System.out.println(Integer.toBinaryString(2 << 44));
System.out.println(Integer.toBinaryString(2 << 55));
Я получаю ниже
1000000000000
100000000000000000000000
100
10000000000000
1000000000000000000000000
Может кто-нибудь объяснить, пожалуйста?
9 ответов
System.out.println(Integer.toBinaryString(2 << 11));
Сдвиги двоичные 2 (10
) в 11 раз влево. Следовательно: 1000000000000
System.out.println(Integer.toBinaryString(2 << 22));
Сдвиги двоичные 2 (10
) в 22 раза влево. Отсюда: 100000000000000000000000
System.out.println(Integer.toBinaryString(2 << 33));
Теперь int имеет 4 байта, следовательно, 32 бита. Поэтому, когда вы делаете сдвиг на 33, это эквивалентно сдвигу на 1. Следовательно: 100
2 из десятичной системы счисления в двоичном виде выглядит следующим образом
10
сейчас, если вы делаете
2 << 11
было бы, 11 нулей будет дополнен на правой стороне
1000000000000
Оператор сдвига влево со знаком "<<" сдвигает битовую комбинацию влево, а оператор сдвига влево со знаком ">>" сдвигает битовую комбинацию вправо. Битовая комбинация задается левым операндом, а число позиций для смещения - правым операндом. Оператор сдвига вправо без знака ">>>" сдвигает ноль в крайнее левое положение, а крайнее левое положение после ">>" зависит от расширения знака [..]
сдвиг влево приводит к умножению на 2 (*2) в терминах или арифметике
Например
2 в двоичном 10
если вы делаете <<1
это было бы 100
который 4
4 в двоичном 100
если вы делаете <<1
это было бы 1000
который 8
Также см
Сдвиг вправо и влево работает одинаково, вот как работает сдвиг вправо; Сдвиг вправо: Оператор сдвига вправо, >>, сдвигает все биты в значении вправо на указанное число раз. Его общая форма:
value >> num
Здесь num указывает количество позиций для сдвига вправо значения в значении. То есть >> перемещает все биты в указанном значении вправо на количество битовых позиций, указанных в num. Следующий фрагмент кода сдвигает значение 32 вправо на две позиции, в результате чего устанавливается значение 8:
int a = 32;
a = a >> 2; // a now contains 8
Когда значение имеет биты, которые "сдвинуты", эти биты теряются. Например, следующий фрагмент кода сдвигает значение 35 вправо на две позиции, что приводит к потере двух младших битов, в результате чего снова устанавливается значение 8.
int a = 35;
a = a >> 2; // a still contains 8
Глядя на ту же операцию в двоичном коде, более четко видно, как это происходит:
00100011 35 >> 2
00001000 8
Каждый раз, когда вы сдвигаете значение вправо, оно делит это значение на два и отбрасывает любой остаток. Вы можете воспользоваться этим для высокопроизводительного целочисленного деления на 2. Конечно, вы должны быть уверены, что не сдвигаете биты с правого конца. Когда вы сдвигаетесь вправо, верхние (самые левые) биты, выставленные правым сдвигом, заполняются предыдущим содержимым верхнего бита. Это называется расширением знака и служит для сохранения знака отрицательных чисел при их правильном смещении. Например, –8 >> 1
является –4
в двоичном виде
11111000 –8 >>1
11111100 –4
Интересно отметить, что если вы сдвинете вправо –1, результат всегда останется –1, поскольку расширение знака продолжает вводить больше единиц в старших разрядах. Иногда нежелательно подписывать значения-расширения, когда вы сдвигаете их вправо. Например, следующая программа преобразует значение байта в его шестнадцатеричное строковое представление. Обратите внимание, что смещенное значение маскируется с помощью AND с 0x0f для отбрасывания любых битов с расширенными знаками, чтобы это значение можно было использовать в качестве индекса в массиве шестнадцатеричных символов.
// Masking sign extension.
class HexByte {
static public void main(String args[]) {
char hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
byte b = (byte) 0xf1;
System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);
}
}
Вот результат этой программы:
b = 0xf1
Я считаю, что это может помочь:
System.out.println(Integer.toBinaryString(2 << 0));
System.out.println(Integer.toBinaryString(2 << 1));
System.out.println(Integer.toBinaryString(2 << 2));
System.out.println(Integer.toBinaryString(2 << 3));
System.out.println(Integer.toBinaryString(2 << 4));
System.out.println(Integer.toBinaryString(2 << 5));
Результат
10
100
1000
10000
100000
1000000
Отредактировано:
Я думаю, что это будет следующим, например:
- Подпись слева сдвиг
[ 2 << 1 ] is => [10 (двоичный из 2) добавить 1 ноль в конце двоичной строки] Следовательно, 10 будет 100, что станет 4.
Сдвиг влево со знаком использует умножение... Так что это также можно рассчитать как 2 * (2^1) = 4. Другой пример [2 << 11] = 2 * (2 ^ 11) = 4096
- Подпись вправо сдвиг
[4 >> 1] is => [100 (двоичный из 4) удалить 1 ноль в конце двоичной строки] Следовательно, 100 будет 10, что становится 2.
Сдвиг вправо со знаком использует деление... Так что это также можно рассчитать как 4 / (2^1) = 2 Другой пример [4096 >> 11] = 4096 / (2 ^ 11) = 2
Это сдвинет биты, заполнив так много 0's
,
Например,
- двоичный
10
который является цифрой2
сдвиг влево на 21000
который является цифрой8
- двоичный
10
который является цифрой2
сдвиг влево на 310000
который является цифрой16
Сдвиг влево, логически простой, если 1<<11 будет стремиться к 2048, а 2<<11 даст 4096
В Java-программировании int a = 2 << 11;
// it will result in 4096
2<<11 = 2*(2^11) = 4096
Сдвиг может быть реализован с типами данных (char, int и long int). Данные с плавающей запятой и двойные данные не могут быть сдвинуты.
value= value >> steps // Right shift, signed data.
value= value << steps // Left shift, signed data.
Типичное использование сдвига переменной и ее присвоения может быть переписано с помощью сокращенных операторов << =, >> = или >>> =, также известных в спецификации как операторы сложного присваивания.
Например,
i >>= 2
дает тот же результат, что и
i = i >> 2