JavaRush /Blog Java /Random-ES /Operaciones bit a bit en Java

Operaciones bit a bit en Java

Publicado en el grupo Random-ES
Probablemente estés familiarizado con la palabra "ritmo". Si no, vamos a conocerlo :) Un bit es la unidad mínima de medida de información en una computadora. Su nombre proviene del inglés " binary digit " - "número binario". Un bit se puede expresar como uno de dos números: 1 o 0. Existe un sistema numérico especial basado en unos y ceros: el binario. No profundizaremos en la jungla de las matemáticas y simplemente señalaremos que cualquier número en Java se puede convertir a su forma binaria. Para hacer esto necesitas usar clases contenedoras. Operaciones bit a bit - 1Por ejemplo, aquí se explica cómo hacerlo para un número int:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Salida de consola:

101010110
1010 10110 (agregué un espacio para facilitar la lectura) es el número 342 en binario. De hecho, dividimos este número en bits individuales: ceros y unos. Es con ellos que podemos realizar operaciones llamadas bit a bit.
  • ~- operador bit a bit "NOT".

Funciona de manera muy simple: recorre cada bit de nuestro número y cambia su valor al opuesto: ceros a unos, unos a ceros. Si lo aplicamos a nuestro número 342, esto es lo que obtenemos: 101010110 es el número 342 en binario 010101001 es el resultado de la expresión ~342 Pero como una variable int ocupa 4 bytes, es decir 32 bits, de hecho, el número en la variable se almacena como: 00000000 00000000 00000001 01010110- el número 342 en una variable de tipo int en java 11111111 11111111 11111110 10101001- el resultado de la expresión ~342 en java Intentemos hacer esto en la práctica:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(~x));
   }
}
Salida de consola:
11111111111111111111111010101001
  • &— operador bit a bit “Y”

Como puede ver, está escrito de manera bastante similar al “Y” lógico ( &&). El operador &&, como recordará, regresa truesolo si ambos operandos son verdaderos. Bitwise &funciona de manera similar: compara dos números bit a bit. El resultado de esta comparación es el tercer número. Por ejemplo, tomemos los números 277 y 432: 100010101 - el número 277 en forma binaria 110110000 - el número 432 en forma binaria A continuación, el operador &compara el primer bit del número superior con el primer bit del inferior. Como se trata de un operador "Y", el resultado será 1 solo si ambos bits son iguales a 1. En todos los demás casos, el resultado será 0. 100010101 & 110110000 _______________ 100010000 - resultado del trabajo & Primero comparamos los primeros bits de dos números entre sí, luego el segundo bit, el tercero, etc. Como puede ver, solo en dos casos ambos bits de los números eran iguales a 1 (el primer y quinto bit). El resultado de todas las demás comparaciones fue 0. Por lo tanto, al final obtuvimos el número 100010000. 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
  • |- bit a bit “O”. El principio de funcionamiento es el mismo: comparamos dos números bit a bit. Sólo que ahora, si al menos uno de los bits es igual a 1, el resultado será igual a 1. Veamos los mismos números: 277 y 432:
100010101 | 110110000 _______________ 110110101 - el resultado del trabajo | Aquí el resultado es diferente: solo los bits que eran ceros en ambos números siguieron siendo ceros. El resultado del trabajo 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 consola:

437
¡Contamos todo correctamente! :)
  • ^- OR exclusivo bit a bit (también conocido como XOR)
Nunca antes nos habíamos encontrado con un operador así. Pero no tiene nada de complicado. Parece una "o" normal. La diferencia es una: el “o” ordinario devuelve truesi al menos un operando es verdadero. Pero no necesariamente uno, si ambos están ahí true, entonces el resultado true. Pero el "o" exclusivo regresa truesólo si uno de los operandos es verdadero. Si ambos operandos son verdaderos, se devolverá un "o" normal true("al menos uno es verdadero"), pero se devolverá un o exclusivo false. Por eso se llama exclusivo. Conociendo el principio de las operaciones bit a bit anteriores, probablemente puedas realizar fácilmente la operación 277^432 tú mismo. Pero será mejor que lo averigüemos juntos una vez más :) 100010101 ^ 110110000 _______________ 010100101 - el resultado del trabajo ^ Aquí está nuestro resultado. Los bits que eran iguales en ambos números devolvieron 0 (la fórmula “uno de” no funcionó). Pero los que formaron pareja 0-1 o 1-0 acabaron convirtiéndose en una unidad. Como resultado, obtuvimos el número 010100101. En el sistema decimal corresponde al número 165. Veamos si calculamos correctamente:
public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Salida de consola:

165
¡Súper! Todo es exactamente como pensábamos :) Ahora es el momento de familiarizarse con las operaciones llamadas cambios de bits. El nombre, en principio, habla por sí solo. Tomaremos un número y moveremos sus bits hacia la izquierda y hacia la derecha :) Veamos cómo se ve:

Desplazamiento a la izquierda

El desplazamiento de bits a la izquierda se indica con el signo << Ejemplo:
public class Main {

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

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
En este ejemplo, el número x=64se llama valor. Son sus partes las que cambiaremos. Desplazaremos los bits hacia la izquierda (esto se puede determinar por la dirección del signo <<) En el sistema binario, el número 64 = 1000000 El número y=3se llama cantidad. La cantidad responde a la pregunta "¿cuántos bits hacia la derecha/izquierda se deben desplazar los bits de un número x?" En nuestro ejemplo, los desplazaremos 3 bits hacia la izquierda. Para que el proceso de cambio sea más claro, veamos la imagen. En nuestro ejemplo usamos números de tipo int. IntOcupan 32 bits de memoria de la computadora. Así es como se ve nuestro número original 64: Operaciones bit a bit - 2Y ahora, en el sentido literal de la palabra, tomamos cada uno de nuestros bits y lo desplazamos 3 celdas hacia la izquierda: Operaciones bit a bit - 3Esto es lo que obtuvimos. Como puede ver, todos nuestros bits se han desplazado y se han agregado 3 ceros más desde fuera del rango. 3 - porque nos estábamos desplazando 3. Si nos moviéramos 10, se agregarían 10 ceros. Entonces, la expresión x << ysignifica "desplazar los bits de un número хy celdas hacia la izquierda". El resultado de nuestra expresión fue el número 1000000000, que en el sistema decimal es igual a 512. Comprobemos:
public class Main {

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

       int z = (x << y);
       System.out.println(z);
   }
}
Salida de consola:

512
¡Así es! En teoría, los bits se pueden desplazar indefinidamente. Pero como tenemos el número int, solo hay 32 celdas disponibles. De ellos, 7 ya están ocupados por el número 64 (1.000.000). Por tanto, si hacemos, por ejemplo, 27 desplazamientos hacia la izquierda, nuestra única unidad se saldrá de rango y “sobrescribirá”. ¡Solo quedarán ceros!
public class Main {

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

       int z = (x << y);
       System.out.println(z);
   }
}
Salida de consola:

0
Como esperábamos, el que pasó más allá de las celdas de 32 bits y desapareció. Obtuvimos un número de 32 bits que consta únicamente de ceros. Operaciones bit a bit - 4Naturalmente, en el sistema decimal corresponde a 0. Una regla simple para recordar los desplazamientos a la izquierda: con cada desplazamiento a la izquierda, el número se multiplica por 2. Por ejemplo, intentemos calcular el resultado de la expresión sin imágenes con bits 111111111 << 3 . multiplicamos tres veces el número 111111111 por 2. Como resultado, obtenemos 888888888. Escribamos el código y verifiquémoslo:
public class Main {

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

888888888

turnos a la derecha

Están indicados por el signo >>. ¡Hacen lo mismo, sólo que en la otra dirección! :) No reinventemos la rueda e intentemos hacer esto con el mismo número int 64.
public class Main {

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

       int z = (x >> y);
       System.out.println(z);
   }
}
Operaciones bit a bit - 5Operaciones bit a bit - 6Como resultado del desplazamiento de 2 hacia la derecha, los dos ceros extremos de nuestro número salieron del rango y se borraron. Obtuvimos el número 10000, que en el sistema decimal corresponde al número 16. Salida a la consola:

16
Una regla sencilla para recordar los desplazamientos a la derecha: cada desplazamiento a la derecha se divide por dos y se descarta el resto. Por ejemplo, 35 >> 2 significa que necesitamos dividir 35 entre 2 2 veces, descartando el resto 35/2 = 17(descartando el resto 1) 17:2 = 8(descartando el resto 1) El total 35 >> 2debe ser igual a 8. Verifique:
public class Main {

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

8

Prioridad de operaciones en Java

A medida que escribe o lee código, a menudo encontrará expresiones en las que se realizan varias operaciones simultáneamente. Es muy importante comprender en qué orden se realizarán; de lo contrario, el resultado puede ser inesperado. Como hay muchas operaciones en Java, todas se separaron en una tabla especial:

Precedencia del operador

Operadores Precedencia
sufijo expr++ expr--
unario ++expr --expr +expr ~ !
multiplicativo * / %
aditivo + -
cambio << >> >>>
relacional < > <= >=en vez de
igualdad == !=
bit a bit Y &
O exclusivo bit a bit ^
bit a bit inclusivo O |
lógico Y &&
O lógico ||
ternario ? :
asignación = += -= *= /= %= &= ^= |= <<= >>= >>>=
Todas las operaciones se realizan de izquierda a derecha, pero teniendo en cuenta su prioridad. Por ejemplo, si escribimos: int x = 6 - 4/2; primero se realizará la operación de división (4/2). Aunque ocupa el segundo lugar en la fila, tiene mayor prioridad. Los paréntesis o corchetes cambian cualquier prioridad al máximo. Probablemente recuerdes esto de la escuela. Por ejemplo, si los sumas a una expresión: int x = (6 - 4)/2; primero se realizará la resta, ya que se calcula entre paréntesis. El operador lógico tiene &&una prioridad bastante baja, como puede verse en la tabla. Por lo tanto, la mayoría de las veces se ejecutará en último lugar. Por ejemplo: boolean x = 6 - 4/2 > 3 && 12*12 <= 119; Esta expresión se ejecutaría así:
  • 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 ejecutarán los operadores de comparación:

    4 > 3 = true

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

    boolean x = true && false;
  • Y finalmente se ejecutará el último operador &&.

    boolean x = true && false;

    boolean x = false;

    El operador de suma ( +), por ejemplo, tiene mayor prioridad que el operador de comparación !=(“no igual”);

    Por tanto en la expresión:

    boolean x = 7 != 6+1;

    primero se realizará la operación 6+1, luego el check 7!=7 (falso), y al final se asignará el resultado a falsela variable x. La asignación generalmente tiene la prioridad más baja de todas las operaciones; consulte la tabla.

¡Uf! Nuestra conferencia fue larga, ¡pero lo lograste! Si no comprende completamente algunas partes de esta y de las conferencias anteriores, no se preocupe, tocaremos estos temas más de una vez en el futuro. Aquí hay algunos enlaces útiles para usted:
  • Operadores lógicos : conferencia JavaRush sobre operaciones lógicas. No llegaremos a ellos pronto, pero puedes leerlos ahora, no habrá ningún daño.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION