"Ciao, Amico!"

"Vorrei anche parlare di bitmask e XOR."

"Sai già che i numeri sono costituiti da bit e puoi eseguire varie operazioni su questi bit. Una maschera di bit è una rappresentazione di diversi valori logici diversi (valori vero/falso) come un singolo numero intero. In questo caso, ogni valore booleano corrisponde a un bit specifico. Ecco come si potrebbe fare:"

"La rappresentazione binaria delle potenze di due (1, 2, 4, 8, 16, 32, ...) implica solo l'impostazione di un bit:"

Numero Rappresentazione binaria
1 0000 0001
2 0000 0010
4 0000 0100
8 0000 1000
16 0001 0000
19 (non una potenza di due) 0001 0011
31 (non una potenza di due) 0001 1111

"Quindi, qualsiasi numero intero può essere trattato come un array di bit o un array di valori booleani."

"Ecco come puoi memorizzare diversi valori booleani in un numero:"

Valori booleani
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
Valori racchiusi in un numero:
int result = 0;
 if (a) result += 1; // 1 == 20 — bit 0
 if (b) result += 2; // 2 == 21 — bit 1
 if (c) result += 4; // 4 == 22 — bit 2
 if (d) result += 8; // 8 == 23 — bit 3

"Ora ogni bit è 1 se la variabile booleana corrispondente era vera."

Nel nostro caso, le variabili a e c erano vere, quindi risultato è uguale a 1+4 == 5

0000 0101
0000 dcba

"Penso di sapere cosa sta succedendo."

"Bene, se capisci, andiamo avanti."

"Un int ha 32 bit. Uno di questi è usato per il segno del numero, e gli altri 31 possono essere usati per memorizzare i valori di 31 variabili booleane."

"Un long ha 64 bit in cui possiamo memorizzare 63 variabili booleane."

"Sì."

"Decine di variabili stipate in un numero. Sono davvero poche."

"Ma dove si applica?"

"Principalmente in situazioni in cui devi memorizzare molte informazioni sugli oggetti. Quando memorizzi molte informazioni su un oggetto, ci sono sempre un paio di dozzine di variabili booleane. "Con questo approccio, sono tutte convenientemente memorizzate in un unico numero ."

"Con enfasi sulla parola 'memorizzato'. Perché in realtà usare il numero non è così conveniente."

"A proposito, è proprio quello che volevo chiedere. Come estraiamo il valore booleano dal numero?"

"Non è affatto complicato. Diciamo che devi determinare se il bit 6 è impostato su 1 (2 alla potenza di cinque è 32). Potremmo controllare in questo modo:"

Combina i numeri in uno:
int a = 32; // 25 == 0010 0000
int b = 8; // 23 == 0000 1000
int c = 2; // 21 == 0000 0010

int result = a + b + c; // 32 + 8 + 2 == 42 == 0010 1010
Estrai i valori controllando bit specifici:
int a = result & 32; // 0010 1010 & 0010 0000 = 0010 0000
int b = result & 8; // 0010 1010 & 0000 1000 = 0000 1000
int c = result & 2; // 0010 1010 & 0000 0010 = 0000 0010

"Pertanto, lavorare con le maschere di bit comporta tre operazioni:"

1)  Impostare un bit specifico su 0

2)  Impostare un bit specifico su 1

3)  Verificare il valore del bit specifico.

"Prendi il bit 6, per esempio."

"Come si imposta il bit 6 su 1?"

Codice Descrizione
result = result | 01000000;
result |= 01000000;
Come si imposta il bit 6 a 1?
result = result & 10111111;
result &= 10111111;
Come si imposta il bit 6 a 0?
c = result & 01000000;
Come si ottiene il valore del bit 6?

"È molto insolito, ma non difficile. Amico, ora sono un programmatore eccezionale."

"E un altro piccolo consiglio su come ottenere facilmente numeri con un bit specifico impostato su 0 o 1: 01000000 o 10111111."

Per questo, abbiamo gli  operatori >> << .

"1 è 2 elevato allo zero. In altre parole, un numero con il bit 0 impostato su 1. Abbiamo bisogno di un numero con il bit 6 impostato."

int c = 1 << 6; // 0000 0001 << 6 == 0100 0000 == 64

"Fantastico! È davvero utile per questi casi."

"Ma cosa succede se ho bisogno di un numero in cui ogni bit è impostato su 1 tranne un bit specifico è impostato su 0?"

"Anche questo non è difficile:"

int d = ~(1 << 6); // ~0100 0000 == 10111111

"In altre parole, è tutto molto semplice:"

Codice Descrizione
result = result | (1 << 6);
result |= (1 << 6);
Come si imposta il bit 6 a 1?
result = result & ~(1 << 6);
result &= ~(1 << 6);
Come si imposta il bit 6 a 0?
c = result & (1 << 6);
Come si ottiene il valore del bit 6?

"Non sembra molto difficile. Ma non me lo ricorderò subito."

"Ma, se incontri un'espressione spaventosa come" risultato &= ~(1 << 6) "nel codice di qualcun altro, saprai che questo qualcuno sta solo lavorando con una maschera di bit."

"E se lo incontri spesso, allora si ricorderà di se stesso per te."

"Ricorda se stesso... suona bene. Grazie per la lezione."