1. Spostamento a sinistra bit a bit
Java ha anche 3 operatori di spostamento bit per bit : se ne hai davvero bisogno, puoi semplicemente spostare tutti i bit di un numero di diverse posizioni a sinistra oa destra.
Per spostare i bit di un numero a sinistra, è necessario l' operatore bitwise shift a sinistra . Così è scritto:
a << b
Dove a
è il numero i cui bit vengono spostati ed b
è un numero che indica quante volte spostare i bit del numero a
a sinistra. Durante questa operazione, i bit di ordine inferiore aggiunti a destra sono zeri.
Esempi:
Esempio | Risultato |
---|---|
|
|
|
|
|
|
|
|
Spostare una cifra a sinistra ha lo stesso effetto di moltiplicare un numero per 2.
Vuoi moltiplicare un numero per 16? 16 è uguale a 2 4 . Quindi sposti le cifre del numero 4 a sinistra
2. Spostamento bit per bit a destra
I bit possono anche essere spostati a destra. Per fare ciò, utilizzare l' operatore di spostamento a destra bit per bit . Così è scritto:
a >> b
Dove a
è il numero i cui bit vengono spostati ed b
è il numero di volte per spostare i bit del numero a
a destra.
Esempi:
Esempio | Risultato |
---|---|
|
|
|
|
|
|
|
|
Lo spostamento di una cifra a destra ha lo stesso effetto della divisione di un numero per 2.
Durante questa operazione, i bit più significativi aggiunti a sinistra sono zeri, ma non sempre !
Il bit più a sinistra di un numero con segno è chiamato bit di segno : se il numero è positivo, lo è 0
; ma se il numero è negativo, questo bit è 1
.
Quando si spostano i bit di un numero a destra, normalmente si sposta anche il valore del bit di segno e il segno del numero va perso. Di conseguenza, per i numeri negativi (dove il bit più a sinistra è 1
), questo bit riceve un trattamento speciale. Quando si spostano i bit di un numero a destra, 0
viene aggiunto a a sinistra se il bit più a sinistra era 0
, e a 1
viene aggiunto a sinistra se il bit più a sinistra era 1
.
Ma nell'esempio sopra, questo non sembra essere il risultato. Perché? Perché i letterali interi sono int
s, e in realtà significa . Cioè, il bit più a sinistra è zero.0b11111111
0b00000000000000000000000011111111
Molti programmatori sono frustrati da questo comportamento di spostamento a destra e preferirebbero che il numero fosse sempre riempito di zeri. Quindi Java ha aggiunto un altro operatore di spostamento a destra .
Così è scritto:
a >>> b
Dove a
è il numero i cui bit vengono spostati ed b
è il numero di volte per spostare i bit del numero a
a destra. Questo operatore aggiunge sempre zeri a sinistra, indipendentemente dal valore originale del bit di segno del numero a
.
3. Lavorare con le bandiere
I programmatori hanno creato un campo di studio quasi completamente nuovo sulla base delle operazioni bit a bit e shift: lavorare con i flag.
Quando i computer avevano pochissima memoria, era molto popolare stipare molte informazioni in un unico numero. Un numero è stato trattato come un array di bit: un int è di 32 bit e un long è di 64 bit.
Puoi scrivere molte informazioni in un tale numero, specialmente se hai bisogno di memorizzare valori logici ( true
o false
). Un singolo long
è come un boolean
array composto da 64 elementi. Questi bit erano chiamati flag e venivano manipolati usando le seguenti operazioni:
-
impostare la bandiera(rendere un bit specifico uguale a
1
) -
reimposta bandiera(rendere un bit specifico uguale a
0
) -
bandiera di controllo(controlla il valore di un bit specifico)
Ed ecco come si fa con gli operatori bit a bit.
Mettere una bandiera
Per impostare un bit specifico su 1
, è necessario eseguire un'operazione OR bit a bit tra il numero di cui si desidera impostare il bit e un numero appositamente creato, dove solo quel bit è 1
.
Ad esempio, supponiamo di avere il numero 0b00001010
e di dover impostare il quinto bit su 1
. In tal caso, è necessario:
0b00001010 | 0b00010000 = 0b00011010
Se il quinto bit fosse già stato impostato su uno, non sarebbe cambiato nulla.
In generale, l'operazione di impostazione di un flag può essere scritta come segue
a | (1 << b)
Dove a
è il numero il cui bit sarà impostato su 1
. Ed b
è la posizione del bit da impostare. L'uso dell'operatore di spostamento a sinistra è super conveniente qui, poiché puoi immediatamente capire con quale bit stiamo lavorando.
Reimpostare un flag
Per azzerare un bit specifico (cioè impostarlo a 0
) senza disturbare gli altri bit, è necessario eseguire un'operazione &
tra il numero di cui si desidera azzerare il bit (cioè impostarlo a 0
) e un numero appositamente creato, dove tutti i bit sono uguali a 1
tranne per il bit che vuoi reimpostare.
Ad esempio, supponiamo di avere il numero 0b00001010
e di dover impostare il 4° bit su 0
. In tal caso, è necessario:
0b00001010 & 0b11110111 = 0b00000010
Se il 4° bit fosse già stato impostato a zero, non sarebbe cambiato nulla.
In generale, l'operazione di azzeramento di un flag può essere scritta come segue
a & ~(1 << b)
Dove a
è il numero il cui bit verrà reimpostato su 0
. Ed b
è la posizione del bit da cancellare.
Per ottenere un numero in cui tutti i bit sono 1
tranne quello che vogliamo sia zero, spostiamo prima di 1 b posizioni a sinistra, quindi utilizziamo l' NOT
operatore bit a bit per invertire il risultato.
Controllo di una bandiera
Oltre ad impostare o resettare uno specifico flag, a volte basta verificare se un dato flag è impostato, cioè se un certo bit è uguale a 1
. Questo è abbastanza facile da fare con un file &
.
Ad esempio, supponiamo di dover verificare se il 4° bit è impostato su 1
nel numero 0b00001010
. Allora devi fare questo:
if ( (0b00001010 & 0b00001000) == 0b00001000 )
In generale, l'operazione di controllo di un flag può essere scritta come segue
(a & (1 << b)) == (1 << b)
Dove a
è il numero il cui bit viene controllato. Ed b
è la posizione della punta da controllare.
4. Crittografia
L' XOR
operazione bit per bit viene spesso utilizzata dai programmatori per una semplice crittografia. In generale, tale crittografia è simile a questa:
result = number ^ password;
Dove number
sono i dati che vogliamo crittografare, password
è un numero speciale utilizzato come "password" per i dati ed result
è il numero crittografato.
number == (number ^ password) ^ password;
La cosa importante qui è che quando l' XOR
operatore viene applicato due volte a un numero, produce il numero originale, indipendentemente dalla "password".
Per recuperare number
da encrypted result
, è sufficiente eseguire nuovamente l'operazione:
original number = result ^ password;
Esempio:
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));
}
}
GO TO FULL VERSION