предисловие
Узнал о побитовых операторах раньше, сдвиг влево<<
Равно умножить на 2, сдвинуть вправо>>
Равно делению на 2. Но когда я посмотрел на исходный код jdk, я нашел>>>
Те, что с тремя символами, я не понимал, что они означают, поэтому я искал и нашел довольно много точек знаний, поэтому я их разобрал.
Прежде всего, мы знаем, что программы, которые мы пишем, в конечном итоге выполняются на нижнем уровне компьютера, а нижний уровень компьютера поддерживает только два символа 0 и 1. Итак, в то время в Интернете была клавиатура с двумя клавишами, 0 и 1, и это была клавиатура, используемая большими парнями. Отодвинься. . .
Давайте сначала рассмотрим, сколько байтов и битов занимают основные типы java (1 байт равен 8 битам):
Типы | количество байтов | количество цифр | размерный ряд |
---|---|---|---|
byte | 1 | 8 | -2^8^~2^8^-1 |
short | 2 | 16 | -2^16^~2^16^-1 |
int | 4 | 32 | -2^32^~2^32^-1 |
long | 8 | 64 | -2^64^~2^64^-1 |
float | 4 | ||
double | 8 | ||
char | 2 | 16 | Тип char может хранить китайский иероглиф |
boolean | 1 | true or false |
Операция сдвига — это операция, которая обрабатывает данные как двоичное число и сдвигает их влево или вправо на несколько битов. В Java есть три оператора сдвига:<<
оператор сдвига влево,>>
подписанный оператор правой смены,>>>
Беззнаковый оператор сдвига вправо. Все три оператора работают только наlong
,int
,short
,byte
Сумма четырех основных целочисленных типовchar
тип. Другие типы, такие как double, не могут использовать побитовые операторы, вы можете проверить это самостоятельно в IDE.
В Java первый бит используется для обозначения положительного или отрицательного числа, первый бит равен нулю, что означает положительное число, а первый бит равен 1, что означает отрицательное число. В качестве примера возьмем простейший 8-битный тип байта:0000 0000
означает 0,0111 1111
Это максимальное значение (2 ^ 8 ^ -1), и после добавления единицы оно становится1000 0000
Затем оно становится минимальным значением (-2^8^). После добавления одного становится1000 0001
В настоящее время значение равно -127. То есть от 0 до максимального значения и затем до минимального значения, а затем от минимального значения до нуля.
оператор сдвига влево<<
оператор сдвига влево<<
после преобразования данных в двоичный,Сдвиньте несколько битов влево, отбросьте старшие биты и заполните младшие биты нулями.
Во-первых, мы можем использовать метод в java для получения двоичного числа:Integer.toBinaryString(int val)
.
Затем мы рассмотрим следующий пример:
public static void main(String[] args) {
int a = 10;
System.out.println("左移前的二进制:"+Integer.toBinaryString(a));
a <<= 2;
System.out.println("左移后的二进制:"+Integer.toBinaryString(a));
System.out.println("左移后的十进制:"+a);
}
Сначала определите число, значение равно 10, напечатайте его двоичное число (1010), а затем выполните операцию сдвига влево на 2 бита. Распечатайте сдвинутый результат и двоичный файл.
左移前的二进制:1010
左移后的二进制:101000
左移后的十进制:40
Видно, что исходный двоичный файл сдвинут влево на два бита с последующим заполнением нулями. 40=10*2*2. Таким образом, сдвиг влево удваивает число. Для сдвига влево на N бит это эквивалентно умножению на 2 ^ n, например 40 = 10 * 2 ^ 2. Давайте посмотрим на левый сдвиг отрицательного числа:
int b = -8;
System.out.println("左移前的二进制:" + Integer.toBinaryString(b));
b <<= 2;
System.out.println("左移后的二进制:" + Integer.toBinaryString(b));
System.out.println("左移后的十进制:" + b);
Мы определяем отрицательное число (-8), печатаем его двоичное число, сдвигаем влево на 2 бита, печатаем его двоичное число после сдвига влево, а затем выводим десятичное число для просмотра.
左移前的二进制:11111111111111111111111111111000
左移后的二进制:11111111111111111111111111100000
左移后的十进制:-32
Хорошо видно, что бинарник сдвинут влево на два бита, первая позиция отброшена, а вторая позиция заполнена нулями. Преобразование в базу 10 также соответствует нашей предыдущей операции: -32 = -8 * 2 * 2.
Подписанный оператор правой смены>>
Только что при сдвиге влево он перемещается влево, старшие биты отбрасываются, а младшие биты заполняются нулями. Однако в операции сдвига вправо есть бит знака, и неправильная операция приведет к тому, что ответ будет отличаться от ожидаемого результата.
Сдвиг вправо со знаком означает перемещение на несколько битов вправо в **, младшие биты отбрасываются, а старшие биты заполняются в соответствии со знаковым битом. ** При выполнении операции сдвига вправо для положительных чисел добавляются старшие биты0
;При сдвиге вправо отрицательного числа добавляется старший бит1
.
Докажем это на примере:
public static void main(String[] args) {
int a = 1024;
System.out.println("a右移前的二进制:" + Integer.toBinaryString(a));
a >>= 4;
System.out.println("a右移后的二进制:" + Integer.toBinaryString(a));
System.out.println("a右移后的十进制:"+a);
int b = -70336;
System.out.println("b右移前的二进制:" + Integer.toBinaryString(b));
b >>= 4;
System.out.println("b右移后的二进制:" + Integer.toBinaryString(b));
System.out.println("b右移后的十进制:"+b);
}
Определены две переменные, a=1024, а затем сдвинуты на 4 бита вправо. b=-70336 также сдвигается на 4 бита вправо. Распечатайте их в двоичном и десятичном виде соответственно до и после движения.
a右移前的二进制:10000000000
a右移后的二进制:1000000
a右移后的十进制:64
b右移前的二进制:11111111111111101110110101000000
b右移后的二进制:11111111111111111110111011010100
b右移后的十进制:-4396
После того, как исходный двоичный код сдвинут вправо, младшие биты отбрасываются, а старший бит дополнительного знака равен 0. После того, как исходный двоичный код b сдвинут вправо, младшие биты отбрасываются, а старшие биты дополняются знаковым битом 1. Это также означает наш предыдущий закон действия: 1024/2^4^=16;-70336/2^4^=-4396.
беззнаковый оператор сдвига вправо>>>
Только что с оператором сдвига вправо со знаком, когда мы движемся вправо, мы берем знак старшего бита, заполняя положительные числа 0 и отрицательные числа 1. Теперь оператор сдвига вправо без знака примерно такой же, как оператор сдвига вправо, за исключением того, что положительные и отрицательные числа больше не различаются, и результатСтаршие биты заполняются нулями, младшие отбрасываются.
Докажем это на примере:
public static void main(String[] args) {
int a = 1024;
System.out.println("a右移前的二进制:" + Integer.toBinaryString(a));
a >>>= 4;
System.out.println("a右移后的二进制:" + Integer.toBinaryString(a));
System.out.println("a右移后的十进制:"+a);
int b = -70336;
System.out.println("b右移前的二进制:" + Integer.toBinaryString(b));
b >>>= 4;
System.out.println("b右移后的二进制:" + Integer.toBinaryString(b));
System.out.println("b右移后的十进制:"+b);
}
Тот же самый пример знакового сдвига вправо только что: на этот раз мы просто заменяем оператор беззнаковым оператором сдвига вправо.
По определению положительные числа фактически не изменяются, потому что положительные числа также заполняются нулями в старших битах при сдвиге вправо со знаком. Он просто меняется, когда значение отрицательное, давайте посмотрим, соответствует ли вывод гипотезе.
a右移前的二进制:10000000000
a右移后的二进制:1000000
a右移后的十进制:64
b右移前的二进制:11111111111111101110110101000000
b右移后的二进制:1111111111111110111011010100
b右移后的十进制:268431060
Верно, что положительное число не изменилось, что подтверждает нашу гипотезу. Тогда это отрицательное число, на этот раз при движении вправо старшие биты заполняются нулями, а младшие отбрасываются. Измененные значения больше не соответствуют нашим предыдущим правилам.
При беззнаковом сдвиге вправо, когда значение положительное, перемещение на один бит эквивалентно делению на 2 в соответствии с предыдущим законом. Но когда значение отрицательное, оно больше не следует закону.
Что происходит, когда количество сдвинутых битов превышает количество битов, занимаемых значением?
Это интересный вопрос, мы только что переместили 2 или 4 бита, что произойдет, если мы превысим количество целых чисел, которое составляет 32 бита? Если мы сдвинем положительное число влево на 32 бита, а младшие нули добавим 32 раза, оно станет равным 0, как и в приведенном ниже коде, что будет конечным результатом a. Станет ли он 0?
public static void main(String[] args) {
int a = 10;
a <<= 32;
System.out.println(a);
}
После того, как мы запустили его, мы обнаружили, что результат a не изменился и по-прежнему равен 10. Если мы изменим его, чтобы сдвинуть влево на 33 бита, его результат станет20
. Так будет ли правило его работы таким, что при превышении количества цифр перемещается только остаток логарифма? Например, для работы с int это фактически операция位数%32
Второсортный.
После многих экспериментов выясняется, что ответом является именно эта гипотеза.Имея дело с типом int, сдвиг вправоx
Битовая операцияx%32
кусочек.
Это то же самое для других типов?
Мы просто использовали тип int, поэтому дляbyte
,short
,char
,long
Все одинаковые?
Сначала посмотрите на тип байта.
public static void main(String[] args) {
byte b = -1;
System.out.println("操作前:"+b);
b >>>= 6;
System.out.println("操作后:"+b);
}
Значение байта определяется как -1, т.е.1111 1111
, то беззнаковый сдвиг вправо на 6 бит, старшие биты заполняются нулями, а младшие отбрасываются, то должно стать0000 0011
Это 3. Давайте запустим этот код, чтобы увидеть, равна ли напечатанная информация 3?
操作前:-1
操作后:-1
Текущий результат не тот, что мы ожидали!
Давайте также распечатаем его двоичный файл, чтобы посмотреть, что произойдет:
public static void main(String[] args) {
byte b = -1;
System.out.println("操作前十进制:"+b);
System.out.println("操作前二进制:"+Integer.toBinaryString(b));
b >>>= 6;
System.out.println("操作后二进制:"+Integer.toBinaryString(b));
System.out.println("操作后十进制:"+b);
}
Затем посмотрите на текущие результаты
操作前十进制:-1
操作前二进制:11111111111111111111111111111111
操作后二进制:11111111111111111111111111111111
操作后十进制:-1
оказалось,Java исправляетbyte
,short
,char
Прежде чем эти три типа будут смещены, они будут преобразованы вint
введите перед битовой манипуляцией. Поскольку мы переназначили его на исходныйbyte
типа, поэтому опять исходил изint
прибытьbyte
Первое преобразование вниз, то есть усечение. Мы можем изменить приведенный выше пример, чтобы более интуитивно обнаруживать запущенный процесс:
public static void main(String[] args) {
byte b = -1;
System.out.println("操作前十进制:"+b);
System.out.println("操作前二进制:"+Integer.toBinaryString(b));
System.out.println("进行无符号右移6位后的十进制:"+(b>>>6));
System.out.println("操作后二进制:"+Integer.toBinaryString(b>>>6));
}
здесь я не использую=
Выполните переназначение, но распечатайте десятичные и двоичные результаты сразу после завершения вычисления.
操作前十进制:-1
操作前二进制:11111111111111111111111111111111
进行无符号右移6位后的十进制:67108863
操作后二进制:11111111111111111111111111
Из распечатанного результата хорошо видно, что сначала он преобразуется в тип int, а затем выполняется битовая операция, после завершения битовой операции выполняется усечение за счет переназначения.
заlong
тип, который является 64-битным, без предварительного преобразования.
Суммировать
Оператор сдвига является основным оператором в Java, а на самом деле поддерживаются только его типы.int
а такжеlong
. справаbyte
,short
,char
Когда тип смещается, он сначала преобразуется вint
введите, а затем работайте. сдвиг влево<<
Оператор эквивалентен умножению на 2. Подписанный оператор правой смены>>
Эквивалентно делению на 2. Использование побитовых операторов в Java лучше, чем умножение*
,Удалить/
оператор более эффективен. беззнаковый сдвиг вправо>>>
При перемещении старшие биты заполняются нулями, а младшие отбрасываются.Это по-прежнему эквивалентно делению на 2, когда оно положительное, но результат больше, когда оно отрицательное (от отрицательного к положительному).
Эта статья опубликована в блогеOpenWriteвыпускать! Электронная почта блогера: liunaijie1996@163.com, если у вас есть какие-либо вопросы, вы можете связаться по электронной почте.