1. Desplazamiento a la izquierda bit a bit
Java también tiene 3 operadores de desplazamiento bit a bit : si realmente lo necesita, puede simplemente desplazar todos los bits de un número varias posiciones hacia la izquierda o hacia la derecha.
Para desplazar los bits de un número a la izquierda, necesita el operador de desplazamiento a la izquierda bit a bit . Así se escribe:
a << b
Where a
es el número cuyos bits se están desplazando, y b
es un número que indica cuántas veces se desplazan los bits del número a
hacia la izquierda. Durante esta operación, los bits de orden inferior agregados a la derecha son ceros.
Ejemplos:
Ejemplo | Resultado |
---|---|
|
|
|
|
|
|
|
|
Desplazar un dígito a la izquierda tiene el mismo efecto que multiplicar un número por 2.
¿Quieres multiplicar un número por 16? 16 es lo mismo que 2 4 . Así que desplazas el número 4 dígitos a la izquierda
2. Desplazamiento bit a bit a la derecha
Los bits también se pueden desplazar hacia la derecha. Para ello, utilice el operador de desplazamiento a la derecha bit a bit . Así se escribe:
a >> b
Donde a
es el número cuyos bits se desplazan y b
es el número de veces que se desplazan los bits del número a
a la derecha.
Ejemplos:
Ejemplo | Resultado |
---|---|
|
|
|
|
|
|
|
|
Desplazar un dígito a la derecha tiene el mismo efecto que dividir un número por 2.
Durante esta operación, los bits de orden superior agregados a la izquierda son ceros, ¡ pero no siempre !
El bit más a la izquierda de un número con signo se llama bit de signo : si el número es positivo, lo es 0
; pero si el número es negativo, este bit es 1
.
Al desplazar los bits de un número hacia la derecha, el valor del bit de signo normalmente también se desplazaría y el signo del número se perdería. En consecuencia, para números negativos (donde el bit más a la izquierda es 1
), este bit recibe un tratamiento especial. Al desplazar los bits de un número a la derecha, se 0
agrega a a la izquierda si el bit más a la izquierda era 0
, y 1
se agrega a a la izquierda si el bit más a la izquierda era 1
.
Pero en el ejemplo anterior, ese no parece ser el resultado. ¿Por qué? Porque los literales enteros son int
s, y en realidad significan . Es decir, el bit más a la izquierda es cero.0b11111111
0b00000000000000000000000011111111
Muchos programadores se sienten frustrados por este comportamiento de desplazamiento a la derecha y preferirían que el número siempre se rellenara con ceros. Así que Java agregó otro operador de desplazamiento a la derecha .
Así se escribe:
a >>> b
Donde a
es el número cuyos bits se desplazan y b
es el número de veces que se desplazan los bits del número a
a la derecha. Este operador siempre añade ceros a la izquierda, independientemente del valor original del bit de signo del número a
.
3. Trabajar con banderas
Los programadores crearon un campo de estudio casi completamente nuevo sobre la base de operaciones bit a bit y de cambio: trabajar con banderas.
Cuando las computadoras tenían muy poca memoria, era muy popular incluir mucha información en un solo número. Un número se trató como una matriz de bits: un int tiene 32 bits y un long tiene 64 bits.
Puede escribir mucha información en dicho número, especialmente si necesita almacenar valores lógicos ( true
o ). false
Un solo long
es como una boolean
matriz compuesta por 64 elementos. Estos bits se denominaron banderas y se manipularon mediante las siguientes operaciones:
-
establecer bandera(hacer un bit específico igual a
1
) -
restablecer bandera(hacer un bit específico igual a
0
) -
marcar la bandera(verifique el valor de un bit específico)
Y así es como se hace con operadores bit a bit.
Poniendo una bandera
Para establecer un bit específico en 1
, debe realizar una operación OR bit a bit entre el número cuyo bit desea establecer y un número creado especialmente, donde solo ese bit es 1
.
Por ejemplo, suponga que tiene el número 0b00001010
y necesita establecer el quinto bit en 1
. En ese caso, es necesario:
0b00001010 | 0b00010000 = 0b00011010
Si el quinto bit ya se hubiera establecido en uno, entonces nada habría cambiado.
En general, la operación de establecer una bandera se puede escribir de la siguiente manera
a | (1 << b)
¿Dónde a
está el número cuyo bit se establecerá en 1
. Y b
es la posición del bit a establecer. Usar el operador de desplazamiento a la izquierda es muy conveniente aquí, ya que puede saber de inmediato con qué bit estamos trabajando.
Restablecimiento de una bandera
Para restablecer un bit específico (es decir, establecerlo en 0
) sin alterar otros bits, debe realizar una &
operación entre el número cuyo bit desea restablecer (es decir, establecer en 0
) y un número creado especialmente, donde todos los bits son iguales 1
excepto para el bit que desea restablecer.
Por ejemplo, suponga que tiene el número 0b00001010
y necesita establecer el cuarto bit en 0
. En ese caso, es necesario:
0b00001010 & 0b11110111 = 0b00000010
Si el cuarto bit ya se hubiera puesto a cero, nada habría cambiado.
En general, la operación de restablecer una bandera se puede escribir de la siguiente manera
a & ~(1 << b)
¿Dónde a
está el número cuyo bit se restablecerá a 0
. Y b
es la posición del bit a borrar.
Para obtener un número donde todos los bits estén 1
excepto el que queremos que sea cero, primero desplazamos 1 b posiciones a la izquierda y luego usamos el NOT
operador bit a bit para invertir el resultado.
Comprobación de una bandera
Además de establecer o restablecer un indicador específico, a veces solo necesita verificar si un indicador determinado está establecido, es decir, si un determinado bit es igual a 1
. Esto es bastante fácil de hacer con un bit a bit &
.
Por ejemplo, suponga que necesita verificar si el cuarto bit está configurado 1
en el número 0b00001010
. Entonces necesitas hacer esto:
if ( (0b00001010 & 0b00001000) == 0b00001000 )
En general, la operación de verificar una bandera se puede escribir de la siguiente manera
(a & (1 << b)) == (1 << b)
¿Dónde a
está el número cuyo bit se está comprobando? Y b
es la posición del bit a comprobar.
4. Cifrado
XOR
Los programadores suelen utilizar la operación bit a bit para el cifrado simple. En general, dicho cifrado se ve así:
result = number ^ password;
¿ Dónde number
están los datos que queremos encriptar? password
Es un número especial que se usa como "contraseña" para los datos y result
es el número encriptado.
number == (number ^ password) ^ password;
Lo importante aquí es que cuando el XOR
operador se aplica dos veces a un número, produce el número original, independientemente de la "contraseña".
Para recuperarse number
del encrypted result
, solo necesita realizar la operación nuevamente:
original number = result ^ password;
Ejemplo:
class Solution
{
public static int[] encrypt(int[] data, int password)
{
int[] result = new int[data.length];
for (int i = 0; i < data.length; i++)
result[i] = data[i] ^ password;
return result;
}
public static void main(String[] args)
{
int[] data = {1, 3, 5, 7, 9, 11};
int password = 199;
// Encrypt the array of data
int[] encrypted = encrypt(data, password);
System.out.println(Arrays.toString(encrypted));
// Decrypt the array of data
int[] decrypted = encrypt(encrypted, password);
System.out.println(Arrays.toString(decrypted));
}
}