CodeGym /Blogue Java /Random-PT /Operadores Java bit a bit
John Squirrels
Nível 41
San Francisco

Operadores Java bit a bit

Publicado no grupo Random-PT
Na lição de hoje, vamos nos familiarizar com os Operadores Java Bitwise e considerar exemplos de como trabalhar com eles. Você provavelmente está familiarizado com a palavra "bit". Se não, vamos relembrar o que significa :) Um bit é a menor unidade de informação em um computador. Seu nome vem de dígito binário . Um bit pode ser expresso por um de dois números: 1 ou 0. Existe um sistema numérico binário especial baseado em uns e zeros. Não vamos mergulhar em uma selva matemática aqui. Observaremos apenas que qualquer número em Java pode ser convertido em formato binário. Para fazer isso, você precisa usar as classes wrapper.
Operadores bit a bit - 1
Por exemplo, veja como você pode fazer isso para um 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 o espaço para facilitar a leitura) é o número 342 no sistema decimal. Na verdade, dividimos esse número em bits individuais: zeros e uns. As operações executadas em bits são chamadas de bit a bit .
  • ~ - bit a bit NÃO.
Esse operador é muito simples: ele passa por cima de cada bit do nosso número e inverte o bit: zeros se tornam um e uns se tornam zeros. Se aplicarmos ao nosso número 342, eis o que acontece: 101010110 é 342 representado como um número binário 010101001 é o valor da expressão ~342 Vamos tentar colocar isso em prática:

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(~x);
   }
}
Saída do console: 169 169 é o nosso resultado ( 010101001 ) no familiar sistema decimal :)
  • & - bit a bit AND
Como você pode ver, ele se parece bastante com o AND lógico ( && ). O operador && , você deve se lembrar, retorna verdadeiro apenas se ambos os operandos forem verdadeiros. Bitwise & funciona de maneira semelhante: compara dois números bit a bit. A comparação produz um terceiro número. Por exemplo, vamos pegar os números 277 e 432: 110110000 é 277 representado como um número binário 1000101011 é 432 representado como um número binário Em seguida, o operador & compara o primeiro bit do número superior com o primeiro bit do número inferior. Como este é um operador AND, o resultado será 1 somente se ambos os bits forem 1. Em qualquer outro caso, o resultado será 0. 100010101 &Operador & Primeiro, comparamos os primeiros bits dos dois números, depois os segundos bits, depois o terceiro e assim por diante. Como você pode ver, em apenas dois casos os bits correspondentes nos números são iguais a 1 (o primeiro e o quinto bits). Todas as outras comparações produziram 0s. No final, obtivemos o número 10001000. No sistema decimal, corresponde ao número 272. Vejamos:

public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Saída do console: 272
  • | - OU bit a bit.
Este operador funciona da mesma forma: comparando dois números bit a bit. Só que agora se pelo menos um dos bits for 1, então o resultado é 1. Vejamos os mesmos números (277 e 432): 100010101 | 110110000 _______________ 110110101 - resultado do | operador Aqui temos um resultado diferente: os únicos bits que permanecem zeros são os bits que eram zeros em ambos os números. O resultado é o número 110110101. No sistema decimal, corresponde ao número 437. Vejamos:

public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Saída do console: 437 Calculamos tudo corretamente! :)
  • ^ - XOR bit a bit (OU exclusivo)
Ainda não encontramos esse operador. Mas não há nada de complicado nisso. É semelhante ao operador OR comum. Há uma diferença: o ordinário OR retorna verdadeiro se pelo menos um operando for verdadeiro. Mas não precisa ser um: se ambos os operandos forem verdadeiros, o resultado será verdadeiro. Mas OU exclusivo retorna verdadeiro apenas se exatamente um dos operandos for verdadeiro. Se ambos os operandos forem verdadeiros, o OU comum retornará verdadeiro ("pelo menos um verdadeiro"), mas XOR retornará falso. É por isso que é chamado OU exclusivo. Sabendo como funcionam os operadores bit a bit anteriores, você provavelmente pode facilmente calcular 277 ^ 432. Mas vamos nos aprofundar juntos mais uma vez :) 100010101 ^ 110110000 _______________ 010100101 - resultado do ^operador Esse é o nosso resultado. Os bits que eram iguais em ambos os números produzem um 0 (significando que o teste "apenas um" falhou). Mas os bits que formavam um par 0-1 ou 1-0 tornaram-se um. Nosso resultado é o número 010100101. No sistema decimal, corresponde ao número 165. Vejamos se nossos cálculos estão corretos:

public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Saída do console: 165 Super! Tudo está como pensávamos :) Agora é hora de se familiarizar com os operadores de deslocamento de bits. O nome fala por si. Pegamos algum número e movemos seus bits para a esquerda ou para a direita :) Vamos ver como fica:

Deslocar para a esquerda

Um deslocamento de bits para a esquerda é indicado por << Veja um exemplo:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       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 os bits do valor que vamos mudar. Deslocaremos os bits para a esquerda (você poderia ter adivinhado isso pela direção do operador << ) No sistema binário, o número 64 = 1000000 O número y = 3 é chamado de distância de deslocamento. A distância de deslocamento indica quantos bits para a direita/esquerda você deseja deslocar os bits do número x Em nosso exemplo, vamos deslocá-los 3 bits para a esquerda. Para ver o processo de mudança com mais clareza, observe a figura. Neste exemplo, usamos int s. Ints ocupam 32 bits na memória do computador. É assim que nosso número original 64 se parece:
Operadores bit a bit - 2
E agora pegamos cada um dos nossos bits e literalmente os deslocamos para a esquerda em 3 lugares:
Operadores bit a bit - 3
Dê uma olhada no que temos. Como você pode ver, todos os nossos bits foram deslocados e outros 3 zeros foram adicionados da borda do intervalo. Três, porque deslocamos em 3. Se tivéssemos deslocado em 10, 10 zeros teriam sido adicionados. Assim, a expressão x << y significa "deslocar os bits do número x para a esquerda em y casas". O resultado da nossa expressão é o número 1000000000, que é 512 no sistema decimal. Vamos checar:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Saída do console: 512 Spot on! Teoricamente, os bits poderiam ser trocados infinitamente, mas como nosso número é um int , temos apenas 32 dígitos binários disponíveis. Destes, 7 já estão ocupados por 64 (1000000). Portanto, se deslocarmos 27 casas para a esquerda, nossa única casa se moverá além do intervalo do tipo de dados e será perdida. Restariam apenas zeros!

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 26;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Saída do console: 0 Como esperado, aquele ultrapassou os 32 bits disponíveis e desapareceu. Terminamos com um número de 32 bits consistindo apenas de zeros.
Operadores bit a bit - 4
Naturalmente, isso corresponde a 0 no sistema decimal. Aqui está uma regra simples para lembrar os deslocamentos para a esquerda: Para cada deslocamento para a esquerda, o número é multiplicado por 2. Vamos tentar calcular a seguinte expressão sem figuras de bits 111111111 << 3 Precisamos multiplicar o número 111111111 por 2 . Como resultado, obtemos 888888888. Vamos escrever algum código e verificar:

public class Main {

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

Deslocar para a direita

Esta operação é denotada por >> . Faz a mesma coisa, mas na outra direção! :) Não vamos reinventar a roda. Vamos tentar com o mesmo int 64.

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 2;// Shift distance

       int z = (x >> y);
       System.out.println(z);
   }
}
Operadores bit a bit - 5
Operadores bit a bit - 6
Como resultado de um deslocamento de 2 para a direita, os dois zeros extremos em nosso número saem do intervalo e são perdidos. Obtemos 10000, que corresponde ao número 16 no sistema decimal Saída do console: 16 Aqui está uma regra simples para lembrar deslocamentos para a direita: Cada deslocamento para a direita divide por dois, descartando qualquer resto. Por exemplo, 35 >> 2 significa que precisamos dividir 35 por 2 duas vezes, descartando os restos 35/2 = 17 (descartar resto 1) 17/2 = 8 (descartar resto 1) No final, 35 >> 2 deveria ser igual a 8. Vamos verificar:

public class Main {

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

Precedência do operador em Java

Ao escrever e ler o código, muitas vezes você encontrará expressões que combinam várias operações. É muito importante entender a ordem em que serão executadas (caso contrário, você pode se surpreender com o resultado) Como o Java possui muitas operações, cada uma delas recebeu um lugar em uma tabela especial:

operador precedente

operadores Precedência
pós-fixado expr++ expr--
unário ++expr --expr +expr ~ !
multiplicativo * / %
aditivo + -
mudança << >> >>>
relacional < > <= >= instância de
igualdade == !=
bit a bit AND &
OR exclusivo bit a bit ^
OU bit a bit inclusivo |
E lógico &&
OU lógico ||
ternário ? :
atribuição = += -= *= /= %= &= ^= |= <<= >>= >>>=
Todas as operações são realizadas da esquerda para a direita, levando em consideração sua precedência. Por exemplo, se escrevermos

int x  = 6 - 4/2;
então a operação de divisão ( 4/2 ) será executada primeiro. Embora venha em segundo lugar, tem maior precedência. Parênteses e colchetes indicam precedência máxima. Você provavelmente se lembra disso na escola. Por exemplo, se você adicioná-los à expressão

int x  = (6 - 4)/2;
então a subtração é realizada primeiro, pois está entre parênteses. A precedência do operador lógico && é bastante baixa (consulte a tabela), portanto, geralmente será a última. Por exemplo:

boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
Esta expressão será executada da seguinte forma:
  • 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;
Em seguida, os operadores de comparação são executados:
  • 4 > 3 = verdadeiro

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

boolean x = true && false;
E, finalmente, o operador AND ( && ) será executado por último.

boolean x = true && false;
boolean x = false;
Por exemplo, o operador de adição( + ) tem uma precedência mais alta que o operador de comparação != (diferente); Portanto, na expressão

boolean x = 7 != 6+1;
a operação 6+1 será executada primeiro, depois a verificação 7 != 7 (que avalia como falso) e, finalmente, a atribuição do resultado (falso) à variável x (a atribuição geralmente tem a precedência mais baixa de todos os operadores ; consulte a mesa). Ufa! Foi uma grande lição, mas você conseguiu! Se você não entendeu totalmente algumas dessas lições ou das anteriores, não se preocupe. Abordaremos esses tópicos mais de uma vez no futuro. Algumas lições do CodeGym sobre operações lógicas e numéricas. Não chegaremos a eles tão cedo, mas não há mal nenhum em você lê-los agora.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION