CodeGym /Blog Java /Random-ES /Operadores bit a bit de Java
Autor
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

Operadores bit a bit de Java

Publicado en el grupo Random-ES
En la lección de hoy, nos familiarizaremos con los operadores bit a bit de Java y consideraremos ejemplos de cómo trabajar con ellos. Probablemente estés familiarizado con la palabra "bit". Si no, recordemos lo que significa :) Un bit es la unidad de información más pequeña en una computadora. Su nombre proviene de dígito binario . Un bit puede expresarse mediante uno de dos números: 1 o 0. Existe un sistema numérico binario especial basado en unos y ceros. No profundizaremos aquí en una jungla matemática. Solo notaremos que cualquier número en Java se puede convertir a forma binaria. Para hacer esto, necesita usar las clases contenedoras.
Operadores bit a bit - 1
Por ejemplo, así es como puedes hacer esto para un int :

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Salida de la consola: 101010110 1010 10110 (agregué el espacio para que sea más fácil de leer) es el número 342 en el sistema decimal. De hecho, hemos desglosado este número en bits individuales: ceros y unos. Las operaciones realizadas en bits se denominan bit a bit .
  • ~ - bit a bit NO.
Este operador es muy simple: pasa sobre cada bit de nuestro número y voltea el bit: los ceros se convierten en unos y los unos en ceros. Si lo aplicamos a nuestro número 342, esto es lo que sucede: 101010110 es 342 representado como un número binario 010101001 es el valor de la expresión ~342 Intentemos poner esto en práctica:

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(~x);
   }
}
Salida de la consola: 169 169 es nuestro resultado ( 010101001 ) en el familiar sistema decimal :)
  • & - bit a bit Y
Como puede ver, se parece bastante al AND lógico ( && ). El operador && , como recordará, devuelve verdadero solo si ambos operandos son verdaderos. Bitwise & funciona de manera similar: compara dos números bit a bit. La comparación produce un tercer número. Por ejemplo, tomemos los números 277 y 432: 110110000 es 277 representado como un número binario 1000101011 es 432 representado como un número binario A continuación, el operador & compara el primer bit del número superior con el primer bit del número inferior. Debido a que este es un operador AND, el resultado será 1 solo si ambos bits son 1. En cualquier otro caso, el resultado es 0. 100010101 &Operador & Primero, comparamos los primeros bits de los dos números, luego los segundos bits, luego el tercero, y así sucesivamente. Como puede ver, en solo dos casos los dos bits correspondientes en los números son iguales a 1 (el primer y el quinto bit). Todas las demás comparaciones produjeron ceros. Así que al final obtuvimos el número 10001000. En el sistema decimal, corresponde al número 272. Comprobemos:

public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Salida de consola: 272
  • | - O bit a bit.
Este operador funciona de la misma manera: comparando dos números bit a bit. Solo que ahora si al menos uno de los bits es 1, entonces el resultado es 1. Veamos los mismos números (277 y 432): 100010101 | 110110000 _______________ 110110101 - resultado de la | operador Aquí tenemos un resultado diferente: los únicos bits que permanecen como ceros son aquellos bits que eran ceros en ambos números. El resultado es el número 110110101. En el sistema decimal corresponde al número 437. Comprobemos:

public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Salida de la consola: 437 ¡Calculamos todo correctamente! :)
  • ^ - XOR bit a bit (OR exclusivo)
Todavía no hemos encontrado este operador. Pero no hay nada complicado al respecto. Es similar al operador OR ordinario. Hay una diferencia: el OR ordinario devuelve verdadero si al menos un operando es verdadero. Pero no tiene por qué ser uno: si ambos operandos son verdaderos, el resultado es verdadero. Pero OR exclusivo devuelve verdadero solo si exactamente uno de los operandos es verdadero. Si ambos operandos son verdaderos, el OR ordinario devuelve verdadero ("al menos uno verdadero"), pero XOR devuelve falso. Por eso se llama OR exclusivo. Sabiendo cómo funcionan los operadores bit a bit anteriores, probablemente pueda calcular fácilmente 277 ^ 432. Pero profundicemos juntos una vez más :) 100010101 ^ 110110000 _______________ 010100101 - resultado de ^operador Ese es nuestro resultado. Esos bits que eran iguales en ambos números producen un 0 (lo que significa que la prueba de "solo uno" falló). Pero los bits que formaban un par 0-1 o 1-0 se convirtieron en unos. Nuestro resultado es el número 010100101. En el sistema decimal, corresponde al número 165. Veamos si nuestros cálculos son correctos:

public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Salida de la consola: 165 ¡Super! Todo es tal como pensábamos :) Ahora es el momento de familiarizarse con los operadores de desplazamiento de bits. El nombre habla por sí mismo. Tomamos un número y movemos sus bits hacia la izquierda o hacia la derecha :) Veamos cómo se ve:

Desplazar a la izquierda

Un desplazamiento de bits hacia la izquierda se indica con << He aquí un ejemplo:

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));
   }
}
En este ejemplo, el número x = 64 se llama valor. Son los bits del valor que cambiaremos. Desplazaremos los bits hacia la izquierda (podría haberlo adivinado por la dirección del operador << ) En el sistema binario, el número 64 = 1000000 El número y = 3 se llama distancia de desplazamiento. La distancia de desplazamiento indica cuántos bits a la derecha/izquierda desea desplazar los bits del número x. En nuestro ejemplo, los desplazaremos 3 bits a la izquierda. Para ver el proceso de cambio más claramente, mire la imagen. En este ejemplo, usamos int s. Los enteros ocupan 32 bits en la memoria de la computadora. Así luce nuestro número 64 original:
Operadores bit a bit - 2
Y ahora tomamos cada uno de nuestros bits y los desplazamos literalmente a la izquierda en 3 lugares:
Operadores bit a bit - 3
Echa un vistazo a lo que tenemos. Como puede ver, todos nuestros bits se han desplazado y se han agregado otros 3 ceros desde el borde del rango. Tres, porque nos desplazamos de 3. Si nos hubiéramos desplazado de 10, se habrían sumado 10 ceros. Así, la expresión x << y significa "desplazar los bits del número x a la izquierda por y lugares". El resultado de nuestra expresión es el número 1000000000, que es 512 en el sistema decimal. Vamos a revisar:

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);
   }
}
Salida de la consola: 512 ¡Puntual! Teóricamente, los bits podrían cambiarse infinitamente, pero debido a que nuestro número es un int , solo tenemos 32 dígitos binarios disponibles. De estos, 7 ya están ocupados por 64 (1000000). Por lo tanto, si cambiamos 27 lugares a la izquierda, nuestro único se movería más allá del rango del tipo de datos y se perdería. ¡Solo quedarían ceros!

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);
   }
}
Salida de la consola: 0 Como era de esperar, el uno se movió más allá de los 32 bits disponibles y desapareció. Terminamos con un número de 32 bits que constaba solo de ceros.
Operadores bit a bit - 4
Naturalmente, esto corresponde a 0 en el sistema decimal. Aquí hay una regla simple para recordar los cambios a la izquierda: para cada cambio a la izquierda, el número se multiplica por 2. Tratemos de calcular la siguiente expresión sin imágenes de bits 111111111 << 3 Necesitamos multiplicar el número 111111111 por 2 . Como resultado, obtenemos 888888888. Escribamos algo de código y verifiquemos:

public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
Salida de consola: 888888888

Desplazar a la derecha

Esta operación se denota por >> . ¡Hace lo mismo, pero en la otra dirección! :) No reinventaremos la rueda. Intentémoslo con el mismo 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 un desplazamiento a la derecha de 2, los dos ceros extremos de nuestro número se salen del rango y se pierden. Obtenemos 10000, que corresponde al número 16 en la salida de la consola del sistema decimal: 16 Esta es una regla simple para recordar los cambios a la derecha: cada cambio a la derecha se divide por dos, descartando cualquier resto. Por ejemplo, 35 >> 2 significa que tenemos que dividir 35 entre 2 dos veces, descartando los restos 35/2 = 17 (descartar el resto 1) 17/2 = 8 (descartar el resto 1) Al final, 35 >> 2 debería sea ​​igual a 8. Comprobemos:

public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
Salida de consola: 8

Precedencia de operadores en Java

Mientras escribe y lee código, a menudo encontrará expresiones que combinan varias operaciones. Es muy importante comprender el orden en que se ejecutarán (de lo contrario, puede que se sorprenda con el resultado) Debido a que Java tiene muchas operaciones, a cada una de ellas se le ha asignado un lugar en una tabla especial:

Precedencia de operadores

Operadores Precedencia
sufijo expr++ expr--
unario ++expr --expr +expr ~ !
multiplicativo * / %
aditivo + -
cambio << >> >>>
relacional < > <= >= instancia de
igualdad == !=
bit a bit Y &
O exclusivo bit a bit ^
bit a bit inclusivo O |
Y lógico &&
O lógico ||
ternario ? :
asignación = += -= *= /= %= &= ^= |= <<= >>= >>>=
Todas las operaciones se realizan de izquierda a derecha, teniendo en cuenta su precedencia. Por ejemplo, si escribimos

int x  = 6 - 4/2;
entonces la operación de división ( 4/2 ) se realizará primero. Aunque viene en segundo lugar, tiene mayor precedencia. Los paréntesis y los corchetes indican la precedencia máxima. Probablemente lo recuerdes de la escuela. Por ejemplo, si los agrega a la expresión

int x  = (6 - 4)/2;
entonces la resta se realiza primero, ya que está encerrada entre paréntesis. La precedencia del operador lógico && es bastante baja (consulte la tabla), por lo que normalmente será el último. Por ejemplo:

boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
Esta expresión se ejecutará de la siguiente manera:
  • 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 continuación, se ejecutan los operadores de comparación:
  • 4 > 3 = verdadero

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

boolean x = true && false;
Y, finalmente, el operador AND ( && ) se ejecutará en último lugar.

boolean x = true && false;
boolean x = false;
Por ejemplo, el operador de suma ( + ) tiene una precedencia mayor que el operador de comparación != (diferente); Por lo tanto, en la expresión

boolean x = 7 != 6+1;
primero se realizará la operación 6+1, luego la verificación 7 != 7 (que se evalúa como falso) y finalmente la asignación del resultado (falso) a la variable x (la asignación generalmente tiene la precedencia más baja de todos los operadores; ver la mesa). ¡Uf! Fue una gran lección, ¡pero lo hiciste! Si no entendiste completamente algunas de estas lecciones o las anteriores, no te preocupes. Tocaremos estos temas más de una vez en el futuro. Un par de lecciones de CodeGym sobre operaciones lógicas y numéricas. No llegaremos a estos en el corto plazo, pero no hay nada de malo en que los lea ahora.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION