JavaRush /Blogue Java /Random-PT /Operações bit a bit em Java

Operações bit a bit em Java

Publicado no grupo Random-PT
Você provavelmente está familiarizado com a palavra “batida”. Se não, vamos conhecer :) Um bit é a unidade mínima de medida de informação em um computador. Seu nome vem do inglês “ dígito binário ” – “número binário”. Um bit pode ser expresso como um de dois números: 1 ou 0. Existe um sistema numérico especial baseado em uns e zeros - binário. Não nos aprofundaremos na selva da matemática e apenas observaremos que qualquer número em Java pode ser convertido para sua forma binária. Para fazer isso, você precisa usar classes wrapper. Operações bit a bit - 1Por exemplo, veja como fazer isso para um número int:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Saída do console:

101010110
1010 10110 (adicionei um espaço para facilitar a leitura) é o número 342 em binário. Na verdade, dividimos esse número em bits individuais - zeros e uns. É com eles que podemos realizar operações chamadas bit a bit.
  • ~- operador “NÃO” bit a bit.

Funciona de forma muito simples: passa por cada bit do nosso número e muda seu valor para o oposto: zeros para uns, uns para zeros. Se aplicarmos ao nosso número 342, é isso que obtemos: 101010110 é o número 342 em binário 010101001 é o resultado da expressão ~342 Mas como uma variável int ocupa 4 bytes, ou seja, 32 bits, na verdade, o número na variável é armazenado como: 00000000 00000000 00000001 01010110- o número 342 em uma variável do tipo int em java 11111111 11111111 11111110 10101001- o resultado da expressão ~342 em java Vamos tentar fazer isso na prática:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(~x));
   }
}
Saída do console:
11111111111111111111111010101001
  • &- operador bit a bit “AND”

Como você pode ver, está escrito de forma bastante semelhante ao “AND” lógico ( &&). O operador &&, como você lembra, retorna trueapenas se ambos os operandos forem verdadeiros. Bitwise &funciona de maneira semelhante: compara dois números bit a bit. O resultado dessa comparação é o terceiro número. Por exemplo, tomemos os números 277 e 432: 100010101 - o número 277 na forma binária 110110000 - o número 432 na forma binária A seguir, o operador &compara o primeiro bit do número superior com o primeiro bit do número inferior. Por se tratar de um operador “AND”, o resultado será igual a 1 somente se ambos os bits forem iguais a 1. Em todos os outros casos, o resultado será 0. 100010101 & 110110000 _______________ 100010000 - resultado do trabalho & Primeiro comparamos os primeiros bits de dois números entre si, depois os segundos bits, o terceiro, etc. Como você pode ver, apenas em dois casos os dois bits dos números foram iguais a 1 (o primeiro e o quinto bits). O resultado de todas as outras comparações foi 0. Portanto, no final obtivemos o número 100010000. No sistema decimal, corresponde ao número 272. Vamos verificar:
public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Saída do console:

272
  • |- “OU” bit a bit. O princípio de operação é o mesmo - comparamos dois números aos poucos. Só que agora se pelo menos um dos bits for igual a 1, o resultado será igual a 1. Vejamos os mesmos números - 277 e 432:
100010101 | 110110000 _______________ 110110101 - o resultado do trabalho | Aqui o resultado é diferente: apenas os bits que eram zeros em ambos os números permaneceram zeros. O resultado do trabalho é o número 110110101. No sistema decimal corresponde ao número 437. Vamos verificar:
public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Saída do console:

437
Contamos tudo corretamente! :)
  • ^- OR exclusivo bit a bit (também conhecido como XOR)
Nunca encontramos tal operador antes. Mas não há nada de complicado nisso. Parece um “ou” normal. A diferença é uma: “ou” comum retorna truese pelo menos um operando for verdadeiro. Mas não necessariamente um – se ambos existirem true– então o resultado true. Mas o “ou” exclusivo retorna trueapenas se um dos operandos for verdadeiro. Se ambos os operandos forem verdadeiros, um “ou” regular retornará true(“pelo menos um é verdadeiro”), mas um ou exclusivo retornará false. É por isso que é chamado de exclusivo. Conhecendo o princípio das operações bit a bit anteriores, você provavelmente poderá executar facilmente a operação 277 ^ 432 sozinho. Mas é melhor descobrirmos juntos mais uma vez :) 100010101 ^ 110110000 _______________ 010100101 - o resultado do trabalho ^ Aqui está o nosso resultado. Os bits iguais em ambos os números retornaram 0 (a fórmula “um de” não funcionou). Mas aqueles que formaram um par 0-1 ou 1-0 acabaram virando uma unidade. Como resultado, obtivemos o número 010100101. No sistema decimal corresponde ao número 165. Vamos ver se calculamos corretamente:
public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Saída do console:

165
Super! Tudo está exatamente como pensamos :) Agora é a hora de nos familiarizarmos com as operações chamadas bit shifts. O nome, em princípio, fala por si. Pegaremos algum número e moveremos seus bits para a esquerda e para a direita :) Vamos ver como fica:

Deslocar para a esquerda

O deslocamento de bits para a esquerda é indicado pelo sinal << Exemplo:
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
Neste exemplo, o número x=64é chamado de valor. São seus pedaços que mudaremos. Deslocaremos os bits para a esquerda (isso pode ser determinado pela direção do sinal <<). No sistema binário, o número 64 = 1000000 O número y=3é chamado de quantidade. Quantidade responde à pergunta “quantos bits para a direita/esquerda os bits de um número devem ser deslocados x?” Em nosso exemplo, iremos deslocá-los 3 bits para a esquerda. Para tornar o processo de mudança mais claro, vejamos a imagem. Em nosso exemplo usamos números do tipo int. Intocupam 32 bits de memória do computador. Esta é a aparência do nosso número original 64: Operações bit a bit - 2E agora nós, no sentido literal da palavra, pegamos cada um dos nossos bits e o deslocamos 3 células para a esquerda: Operações bit a bit - 3Foi isso que obtivemos. Como você pode ver, todos os nossos bits foram deslocados e mais 3 zeros foram adicionados fora do intervalo. 3 - porque estávamos mudando 3. Se estivéssemos mudando 10, seriam adicionados 10 zeros. Portanto, a expressão x << ysignifica “deslocar os bits de um número хy células para a esquerda”. O resultado da nossa expressão foi o número 1000000000, que no sistema decimal é igual a 512. Vamos verificar:
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
Saída do console:

512
Isso mesmo! Em teoria, os bits podem ser deslocados indefinidamente. Mas como temos o número int, existem apenas 32 células disponíveis. Destes, 7 já estão ocupados pelo número 64 (1.000.000). Portanto, se fizermos, por exemplo, 27 deslocamentos para a esquerda, nossa única unidade sairá do intervalo e “sobrescreverá”. Apenas zeros permanecerão!
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 26;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
Saída do console:

0
Como esperávamos, aquele ultrapassou as células de 32 bits e desapareceu. Obtivemos um número de 32 bits que consiste apenas em zeros. Naturalmente, no sistema decimal corresponde a 0. Uma regra simples para lembrar os deslocamentos à esquerda: a cada deslocamento à esquerda, o número é multiplicado por 2. Por exemplo, vamos Operações bit a bit - 4tentar calcular o resultado da expressão sem imagens com bits. 111111111 << 3para multiplicar três vezes o número 111111111 por 2. Como resultado, obtemos 888888888. Vamos escrever o código e verificá-lo:
public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
Saída do console:

888888888

Mudanças à direita

Eles são indicados pelo sinal >>. Eles fazem a mesma coisa, só que na outra direção! :) Não vamos reinventar a roda e tentar fazer isso com o mesmo número int 64.
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 2;//quantity

       int z = (x >> y);
       System.out.println(z);
   }
}
Operações bit a bit - 5Operações bit a bit - 6Como resultado do deslocamento de 2 para a direita, os dois zeros extremos do nosso número saíram do intervalo e foram apagados. Obtivemos o número 10000, que no sistema decimal corresponde ao número 16. Saída para o console:

16
Uma regra simples para lembrar deslocamentos à direita: cada deslocamento à direita divide por dois, descartando qualquer resto. Por exemplo, 35 >> 2 significa que precisamos dividir 35 por 2 2 vezes, descartando o resto 35/2 = 17(descartando resto 1) 17:2 = 8(descartando resto 1) O total 35 >> 2deve ser igual a 8. Verifique:
public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
Saída do console:

8

Precedência de operações em Java

Ao escrever ou ler código, você frequentemente encontrará expressões nas quais diversas operações são executadas simultaneamente. É muito importante entender em que ordem serão realizadas, caso contrário o resultado pode ser inesperado. Como existem muitas operações em Java, todas foram separadas em uma tabela especial:

operador precedente

Operadores Precedência
pós-fixado expr++ expr--
unário ++expr --expr +expr ~ !
Multiplicativo * / %
aditivo + -
mudança << >> >>>
relacional < > <= >=instancia de
igualdade == !=
E bit a bit &
OR exclusivo bit a bit ^
OU bit a bit inclusivo |
lógico E &&
OU lógico ||
ternário ? :
atribuição = += -= *= /= %= &= ^= |= <<= >>= >>>=
Todas as operações são realizadas da esquerda para a direita, mas tendo em conta a sua prioridade. Por exemplo, se escrevermos: int x = 6 - 4/2; primeiro será realizada a operação de divisão (4/2). Embora ela seja a segunda na fila, ela tem maior prioridade. Parênteses ou colchetes alteram qualquer prioridade para o máximo. Você provavelmente se lembra disso da escola. Por exemplo, se você adicioná-los a uma expressão: int x = (6 - 4)/2; a subtração será realizada primeiro, pois é calculada entre parênteses. O operador lógico tem &&uma prioridade bastante baixa, como pode ser visto na tabela. Portanto, na maioria das vezes será executado por último. Por exemplo: boolean x = 6 - 4/2 > 3 && 12*12 <= 119; Esta expressão seria executada assim:
  • 4/2 = 2

    boolean x = 6 - 2 > 3 && 12*12 <= 119;
  • 12*12 = 144

    boolean x = 6 - 2 > 3 && 144 <= 119;
  • 6-2 = 4

    boolean x = 4 > 3 && 144 <= 119;
  • A seguir serão executados os operadores de comparação:

    4 > 3 = true

    boolean x = true && 144 <= 119;
  • 144 <= 119 = false

    boolean x = true && false;
  • E finalmente, o último operador será executado &&.

    boolean x = true && false;

    boolean x = false;

    O operador de adição ( +), por exemplo, tem precedência maior que o operador de comparação !=(“diferente”);

    Portanto na expressão:

    boolean x = 7 != 6+1;

    primeiro será realizada a operação 6+1, depois a verificação 7!=7 (falso), e ao final o resultado será atribuído à falsevariável x. A atribuição geralmente tem a prioridade mais baixa de todas as operações – veja a tabela.

Ufa! Nossa palestra foi longa, mas você conseguiu! Se você não entendeu completamente algumas partes desta e das palestras anteriores, não se preocupe, abordaremos esses tópicos mais de uma vez no futuro. Aqui estão alguns links úteis para você:
  • Operadores Lógicos - Palestra JavaRush sobre operações lógicas. Não chegaremos a eles tão cedo, mas você pode lê-los agora, não haverá nenhum dano
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION