- Operadores Lógicos em Java
- Operador de negação lógica!
- AND lógico - &, bem como AND - && condicional
- OR lógico é o operador |, assim como OR condicional é o operador ||
- XOR - lógico exclusivo OR - operador ^
- Prioridade de operações lógicas
- Expressões lógicas complexas
- Operadores bit a bit (bit a bit)
- Operadores bit a bit &, | e ^
- Código adicional
- Operador de negação bit a bit ~
Operações Lógicas em Java
As operações lógicas são realizadas usando operadores booleanos. Perdoe a tautologia, mas é exatamente assim que as coisas são. Operações lógicas básicas (em programação e matemática) podem ser aplicadas a argumentos lógicos (operandos) e também podem ser usadas para formar expressões mais complexas, semelhantes às operações aritméticas com números. Por exemplo a expressão:
(a | b) | (c < 100) & !(true) ^ (q == 5)
é uma expressão lógica complexa com quatro operandos: (a | b)
, onde а
e b
são variáveis de tipo boolean
(c < 100)
(true)
(q == 5)
. Por sua vez, uma expressão lógica simples (a | b)
também consiste em dois argumentos de operando. Um operando lógico é uma expressão que pode ser considerada verdadeira ou falsa, verdadeira ou falsa . Na linguagem Java, um operando booleano é uma expressão do tipo boolean
ou booleano, por exemplo:
(2 < 1)
— operando lógico, seu valor é falsotrue
- um operando lógico cujo valor é obviamente verdadeiroboolean a
- também pode ser um operando lógico, como Boolean aint a = 2
- não é um operando lógico , é apenas uma variável do tipoint
String a = "true"
também não é um operando lógico . Esta é uma string cujo valor de texto é"true"
.
- Negação lógica , também conhecida
NOT
como inversão. Em Java, é indicado pelo!
símbolo “ ” antes do operando. Aplica-se a um operando. - Lógico e , também é
AND
uma conjunção. Indicado por um símbolo “&
” entre os dois operandos aos quais está aplicado. - Lógico ou em Java , também é -
OR
, também é disjunção. Em Java, é indicado pelo símbolo “|
” entre dois operandos. - Disjunção exclusiva ou estrita
XOR
. Em Java, é indicado pelo símbolo “^
” entre dois operandos. - Em Java, os operadores lógicos incluem o condicional ou , denotado como
||
, bem como o condicional e -&&
.
==
não é considerado um operador lógico. Atenção! Em Java, os operadores lógicos&
e|
também^
se aplicam a números inteiros. Nesse caso, eles funcionam de maneira um pouco diferente e são chamados de operadores lógicos bit a bit (ou bit a bit). Sobre eles - no final do artigo. Vejamos uma tabela com uma breve descrição de cada um dos operadores lógicos Java e, a seguir, iremos descrevê-los com mais detalhes e fornecer exemplos de código.
Operador Java | Nome | Tipo | Pequena descrição | Exemplo |
---|---|---|---|---|
! |
“Não” lógico (negação) | Unário | !x significa “não x”. Retorna verdadeiro se o operando for falso . Retorna false se o operando for true . |
boolean x = true; Então // !x == false |
& |
E lógico ( AND , multiplicação) |
Binário | Retorna verdadeiro se ambos os operandos forem verdadeiros . | a = true; b = false; Então a & b == false |
| |
OR lógico ( OR , adição) |
Binário | Retorna verdadeiro se pelo menos um dos operandos for verdadeiro . | a = true; b = false; Então a | b == true |
^ |
OU exclusivo lógico ( XOR ) |
Binário | Retorna verdadeiro se um e apenas um dos operandos for verdadeiro . Retorna false se ambos os operandos forem true ou false . Essencialmente, retorna verdadeiro se os operandos forem diferentes. | a = true; b = false; Então a ^ b == true |
&& |
AND condicional (AND lógico curto) | Binário | O mesmo que , & mas se o operando à esquerda & for false , este operador retornará false sem verificar o segundo operando. |
|
|| |
OU condicional (OU lógico curto) | Binário | O mesmo que , | mas se o operador à esquerda for true , o operador retornará true sem verificar o segundo operando. |
Operador de negação lógica!
Este operador é unário, o que significa que se aplica a uma única expressão ou operando booleano. É muito simples de entender, como qualquer negação: o operador simplesmente muda o significado da expressão para o seu oposto. Tabela verdade ou resultados da execução de uma operação de negação:O valor de um | !a |
falso | verdadeiro |
verdadeiro | falso |
public class Solution {
public static void main(String[] args) {
boolean a = true;
System.out.println(!a); // here our boolean expression reverses its value
System.out.println(!false); // non-false expression, as you might guess, will be equal to... what?
System.out.println(!(2 < 5)); // expression (2 < 5) is true, so its negation is false
}
}
A saída do programa será a seguinte:
false
true
false
AND lógico - &, bem como AND - && condicional
AND lógico ou conjunção é aplicado a duas expressões, e seu resultado será verdadeiro somente se ambos os operandos forem verdadeiros. Ou seja, se um dos operandosa
ou b
for false , então a expressão a & b
será falsa independente do valor do segundo operador. Se você imaginar que verdadeiro é o número 1 e falso é 0, então o operador &
funciona exatamente da mesma forma que a multiplicação regular. Portanto, AND lógico é frequentemente chamado de “multiplicação lógica”. E, aliás, esse fato ajuda a lembrar rapidamente o funcionamento do operador &
e não confundi-lo com o operador lógico ou |
. Tabela verdade E, também é resultado do trabalho do operador&
a | b | a&b |
verdadeiro | verdadeiro | verdadeiro |
verdadeiro | falso | falso |
falso | verdadeiro | falso |
falso | falso | falso |
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean c = true;
System.out.println(a & b); // if we multiply true by false, we will definitely get false
System.out.println(a & c); // true to true will be true
System.out.println(false & (2 > 5));
System.out.println((2 < 5) & false);
// regardless of the truthfulness of the expression in brackets, in which case we have to be content with false
}
}
Resultado do programa:
false
true
false
false
O operador &&
às vezes é chamado de “AND curto”. Produz o mesmo resultado ao trabalhar com operandos lógicos que o operador &
. No entanto, há uma diferença em seu trabalho em si. Então, você já percebeu que se a & b
o operando da expressão ( ) a
for falso , então não faz sentido verificar o valor do operando b
: o resultado da operação será definitivamente falso . Portanto, se não precisamos fundamentalmente do valor do segundo operando, utilizando-o &&
reduzimos o número de cálculos no programa. Se substituirmos todos os operadores do exemplo &
por &&
, o resultado será exatamente o mesmo, mas o programa em si será executado um pouco mais rápido (embora não notemos isso, já que estamos falando de mili-micro... em resumo , unidades de tempo muito pequenas).
OR lógico é o operador |, assim como OR condicional é o operador ||
O operador OR em Java é representado pelo símbolo|
. Um OR lógico ou disjunção é aplicado a duas expressões e seu resultado será falso se e somente se ambos os operandos forem falsos. Aqui observamos, até certo ponto, a mesma imagem que no caso do operador &
, mas exatamente o oposto. Ou seja, se pelo menos um operando for true , então a | b
é garantido que a expressão seja verdadeira independentemente do valor do segundo operador. Se &
se comportar como uma multiplicação lógica, então OR é uma adição lógica, se você imaginar que verdadeiro é 1 e falso é 0. Lembre-se de que a adição lógica funciona de maneira diferente da adição normal. 1 + 1 neste caso não é igual a 2, mas a 1 (o número 2 simplesmente não existe neste sistema). Às vezes a disjunção é entendida como o máximo de 0 e 1, e neste caso, se pelo menos um operando for igual a 1 ( true ), obtemos exatamente true . Tabela verdade OR, também conhecida como resultado do operador |
:
a | b | uma | b |
verdadeiro | verdadeiro | verdadeiro |
verdadeiro | falso | verdadeiro |
falso | verdadeiro | verdadeiro |
falso | falso | falso |
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean c = true;
System.out.println(!a | b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
System.out.println(a | c);
System.out.println((2 < 5) | false); // expression (2 < 5) is true, which means that for any second operand we get a true result
System.out.println((2 > 5) | true);
}
}
Resultado:
false
true
true
true
Se usarmos o operador condicional OR - ||
em vez de |
, obteremos exatamente o mesmo resultado, mas, como no caso do condicional AND &&
, ele agirá economicamente: se “encontrarmos” o primeiro operando igual a true , o valor de o segundo operando não é verificado, mas imediatamente o resultado é true .
XOR Java - lógico exclusivo OR - operador ^
XOR
, adição de módulo 2, XOR lógico, subtração lógica, disjunção estrita, complemento bit a bit... o operador ^
tem muitos nomes na álgebra booleana. O resultado da aplicação deste operador a dois operandos será verdadeiro se os operandos forem diferentes e falso se os operandos forem iguais. Portanto, é conveniente compará-lo com a subtração de zeros ( false ) e uns ( true ). Tabela verdade XOR
, também conhecida como resultado do operador ^
:
Booleano a | Booleano b | a^b |
verdadeiro | verdadeiro | falso |
verdadeiro | falso | verdadeiro |
falso | verdadeiro | verdadeiro |
falso | falso | falso |
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean c = true;
System.out.println(!a ^ b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
System.out.println(a ^ c);
System.out.println((2 < 5) ^ false);
System.out.println((2 > 5) ^ true);
}
}
Resultado:
false
false
true
true
Prioridade de operações lógicas
Assim como na matemática, na programação os operadores possuem uma ordem de execução específica quando aparecem na mesma expressão. Os operadores unários têm vantagens sobre os binários e a multiplicação (mesmo lógica) sobre a adição. Classificamos os operadores lógicos no topo da lista, quanto maior for sua prioridade:!
&
^
|
&&
||
&
e |
) têm precedências diferentes:
public class Solution {
public static void main(String[] args) {
boolean a = true, b = true, c = false;
System.out.println(a | b & c);
}
Se tivéssemos trabalhado da esquerda para a direita, ou seja, aplicasse primeiro o operador |
e depois - &
, teríamos recebido o valor false . Mas, na verdade, se você executar este programa, terá certeza de que a saída será verdadeira , pois o operador lógico AND &
terá maior prioridade que o operador lógico OR |
. Para evitar confusão, você precisa lembrar o que &
se comporta como multiplicação e |
o que se comporta como adição. Você pode alterar a ordem de prioridade. Basta usar colchetes, assim como na matemática escolar. Vamos mudar um pouco nosso código de exemplo:
public class Solution {
public static void main(String[] args) {
boolean a = true, b = true, c = false;
System.out.println((a|b)&c);
}
E aí? Primeiro usamos a adição lógica entre colchetes e depois a multiplicação. O resultado será falso .
Expressões lógicas complexas
Claro, podemos combinar expressões e operadores booleanos. Vamos relembrar a expressão do início do artigo:(a | b) | (c < 100) & !(true) ^ (q == 5)
Agora não parece tão assustador. Vamos escrever um programa que exiba seu valor, tendo previamente determinado os valores de a
, b
, с
e q
. Exemplo de cálculo do valor de uma expressão booleana complexa
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
int c = 25;
int q = 2;
System.out.println((a|b) | (c < 100) & !(true)^(q == 5));
}
}
Observação:q
nossa variável é do tipo int
, mas q == 5
esta é uma expressão booleana, e é igual a false , pois acima inicializamos com q
o número 2. O mesmo acontece com a variável c
. Este número é igual a 25, mas (c < 100) é uma expressão booleana igual a true . O resultado deste programa:
true
Expressões booleanas complexas podem ser usadas para testar condições muito complexas e ramificadas, mas não devem ser usadas em demasia: elas dificultam a leitura do código.
Operadores bit a bit (bit a bit)
No início do artigo, mencionamos que os operadores&
, |
e ^
podem ser usados em relação aos tipos inteiros Java. Neste caso, eles são operadores bit a bit. Eles também são chamados de bit a bit, pois um dígito é um bit e essas operações funcionam especificamente com bits. É claro que eles funcionam de maneira um pouco diferente dos operadores lógicos e, para entender exatamente como, você precisa saber o que é um sistema numérico binário. Se você não sabe nada sobre isso ou esqueceu completamente, sugerimos que você primeiro leia o artigo Java: bits e bytes e lembre a todos que no sistema numérico binário existem apenas dois dígitos - 0 e 1, e todos os dados no computador é representado precisamente com o uso de zeros e uns condicionais. Qualquer um dos números com os quais estamos acostumados (decimais; para eles existem 10 dígitos diferentes de 0 a 9, com os quais escrevemos quaisquer números) pode ser representado no sistema numérico binário. Você pode converter um número decimal em binário usando a divisão sequencial em uma coluna usando a base do sistema numérico (2). Os restos da divisão em cada etapa, escritos em ordem inversa, nos darão o número binário desejado. Aqui, por exemplo, está a conversão do número decimal 103 em representação binária:
Sistema numérico binário no curso JavaRush No curso JavaRush, eles falam sobre o sistema de numeração binária enquanto estudam a missão MultiThreading (nível 10, aula 1), após a palestra há diversas tarefas para consolidação. No entanto, este tópico não é nada difícil e, mesmo que você ainda não tenha chegado tão longe no curso, provavelmente descobrirá. |
&
, |
e ^
Java também usa operadores bit a bit:
~
operador de negação bit a bit>>
deslocamento bit a bit para a direita>>>
deslocamento à direita bit a bit não assinado<<
deslocamento bit a bit para a esquerda
Operadores bit a bit &, | e ^
Vejamos um exemplo de como esses operadores funcionam. Digamos que temos dois números inteiros:int a = 25;
int b = 112;
Precisamos aplicar três operações a eles e &
exibir o resultado na tela. Aqui está o código do programa: |
^
public class Solution {
public static void main(String[] args) {
int a = 25;
int b = 112;
int res1 = a & b;
int res2 = a | b;
int res3 = a ^ b;
System.out.println("a & b = " + res1);
System.out.println("a | b = " + res2);
System.out.println("a ^ b = " + res3);
}
}
O resultado do programa é o seguinte:
a & b = 16
a | b = 121
a ^ b = 105
Se você não entende o que está acontecendo, o resultado parece muito, muito misterioso. Na verdade, tudo é mais simples do que parece. Os operadores bit a bit “vêem” os números dos operandos em sua forma binária. E então eles aplicam operadores lógicos &
, |
ou ^
aos dígitos (bits) correspondentes de ambos os números. Assim, para &
o último bit da representação binária do número 25 soma-se logicamente ao último bit da representação binária do número 112, o penúltimo bit com o penúltimo, e assim por diante: A mesma lógica pode ser rastreada no caso de |
e ^
.
Deslocamento de bit para esquerda ou direita
Existem vários operadores de deslocamento de bits em Java. Os operadores mais comumente usados<<
são e >>
. Eles deslocam a representação binária de um número para a esquerda ou para a direita, respectivamente, e no caso de um deslocamento para a direita, preservando o sinal (explicaremos o que significa preservar o sinal abaixo). Existe outro operador de deslocamento para a direita >>>
. Faz a mesma coisa, mas >>
não salva o sinal. Então, vamos dar uma olhada no trabalho deles usando um exemplo. int a = 13
a << 1
desloca todos os bits da representação binária do número a para a esquerda em 1 bit. Para simplificar, vamos imaginar o número 13 em binário como 0000 1101. Na verdade, esse número se parece com isto: 00000000 00000000 00000000 00001101, já que Java int
aloca 4 bytes ou 32 bits para números. No entanto, isso não desempenha um papel no exemplo, portanto, neste exemplo consideraremos nosso número como um byte. O bit vago à direita é preenchido com zeros. Como resultado desta operação, obtemos o número 26. a << 2
Ele desloca todos os bits da representação binária do número a
para a esquerda em 2 bits, e os dois bits vagos à direita são preenchidos com zeros. Como resultado, obteremos o número 52. a << 3
O resultado será 104... Notou o padrão? O deslocamento bit a bit a
para a esquerda em n posições funciona como multiplicar um número a
por 2 elevado à potência de n. O mesmo se aplica aos números negativos. Isso -13 << 3
dará o resultado -104. a >> n
desloca a representação binária de um número n posições para a direita. Por exemplo, 13 >> 1
transforma o número 1101 no número 0110, ou seja, 6. E 13 >> 2
o resultado será 3. Ou seja, em essência, aqui dividimos o número por 2 elevado à potência de n, onde n é o número de turnos para a direita, mas com uma ressalva: se o número for ímpar, durante esta operação parecemos redefinir o último bit do número. Mas com os negativos a situação é um pouco diferente. Digamos que você tente verificar o que o programa produzirá se você solicitar que ele execute uma operação -13 >> 1
. Você verá o número -7, não -6, como você imagina. Isso acontece devido à forma como os números negativos são armazenados em Java e outras linguagens de programação. Eles são armazenados no que é chamado de código complementar. Neste caso, o dígito mais significativo (o da esquerda) é indicado abaixo do sinal. No caso de um número negativo, o dígito mais significativo é 1.
Código adicional
Vamos considerar o númeroint a = 13
. Se no programa você imprimir sua representação binária no console usando o comando System.out.println(Integer.toBinaryString(a));
, obteremos 1101. Na verdade, esta é uma notação abreviada, pois o número do tipo int
ocupa 4 bytes na memória, então o computador o “vê” mais assim:
00000000 00000000 00000000 00001101
O dígito mais significativo é zero, o que significa que temos um número positivo. Para converter em código adicional:
-
Escrevemos o número -13 no chamado “código direto”. Para fazer isso, altere o dígito mais significativo do número para 1.
Resultado da ação:10000000 0000000 0000000 00001101
-
A seguir, invertemos todos os bits (mudamos 0 para 1 e 1 para 0), exceto o bit de sinal. Na verdade, já mudamos isso.
Resultado da ação:11111111 11111111 11111111 11110010
(sim, as etapas 1 e 2 podem ser combinadas, mas é melhor pensar dessa forma)
- Adicione 1 ao número resultante.
Resultado da ação:11111111 11111111 11111111 11110011
-13 >> 1
. Como nosso operador >>
preserva o sinal, nesta operação todos os bits liberados à esquerda são preenchidos não com zeros, mas com uns. Assim, mudando o número
11111111 11111111 11111111 11110011
um bit para a direita, resultando na seguinte sequência de bits:
11111111 11111111 11111111 11111001
Se convertermos esse número em código direto (ou seja, primeiro subtrair 1 e depois inverter todos os bits, exceto o primeiro), obteremos o número:
10000000 00000000 00000000 00000111
ou -7. Agora que entendemos o operador de deslocamento à direita com preservação de sinal, ficará claro como ele difere do operador >>>
. a >>> n
— esta operação é um deslocamento sem sinal, ou seja, desloca a representação binária de um número a
para a direita em n bits, mas preenche os n bits vagos à esquerda não com uns, como o operador >>
, mas com zeros. Vamos fazer a operação -13 >>> 1
. Já temos o número -13
em complemento de dois:
11111111 11111111 11111111 11110011
Deslocando 1 bit para a direita e preenchendo o bit livre com zero, obtemos o seguinte número:
01111111 11111111 11111111 11111001
O que dá o número em notação decimal 2147483641
.
Operador de negação bit a bit ~
Este operador unário funciona de forma muito simples: ele inverte cada bit da representação binária de um inteiro. Vamos pegar o número-13
:
11111111 11111111 11111111 11110011
A operação de negação bit a bit ~13
simplesmente reverterá o valor de cada bit. Como resultado obtemos:
00000000 00000000 00000000 00001100
Ou 12
na forma decimal.
Breves conclusões
- Todos os operadores lógicos se aplicam a expressões booleanas, ou seja, aquelas que podem ser consideradas verdadeiras ou falsas .
- Если операторы
&
,|
or^
применяются к числам, речь идёт уже не о логических операциях, а о побитовых. То есть оба числа переводятся в двоичную систему и к этим числам побитово применяют операции логического сложения, умножения or вычитания. - В математической логике операторам
&
и|
соответствуют конъюнкция и дизъюнкция. - Логическое И похоже на умножения 1 (true) и 0 (false).
- Логическое ИЛИ напоминает поиск максимума среди 1 (true) и 0 (false).
- Для побитового отрицания целого числа a используется операция
~a
. - Для логического отрицания булевского выражения a используется операция
!a
. - Отрицательные числа хранятся и обрабатываются в дополнительном codeе.
- Поразрядный сдвиг вправо может сохранять знак (
>>
), а может — не сохранять (>>>
).
GO TO FULL VERSION