JavaRush /Java Blog /Random-IT /Operazioni bit a bit in Java

Operazioni bit a bit in Java

Pubblicato nel gruppo Random-IT
Probabilmente hai familiarità con la parola "battito". In caso contrario, scopriamolo :) Un bit è l'unità minima di misura delle informazioni in un computer. Il suo nome deriva dall'inglese " binary digit " - "numero binario". Un bit può essere espresso come uno di due numeri: 1 o 0. Esiste un sistema numerico speciale basato su uno e zero: binario. Non entreremo nella giungla della matematica e noteremo semplicemente che qualsiasi numero in Java può essere convertito nella sua forma binaria. Per fare ciò è necessario utilizzare le classi wrapper. Operazioni bit a bit - 1Ad esempio, ecco come farlo per un numero int:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Uscita console:

101010110
1010 10110 (ho aggiunto uno spazio per leggibilità) è il numero 342 in binario. In realtà abbiamo diviso questo numero in singoli bit: zero e uno. È con loro che possiamo eseguire operazioni chiamate bit a bit.
  • ~— operatore “NOT” bit per bit.

Funziona in modo molto semplice: attraversa ogni bit del nostro numero e cambia il suo valore nel contrario: zero in uno, uno in zero. Se lo applichiamo al nostro numero 342, questo è ciò che otteniamo: 101010110 - il numero 342 in binario 010101001 - il risultato dell'espressione ~342 Ma poiché una variabile int occupa 4 byte, cioè 32 bit, infatti, il numero nella variabile viene memorizzato come: 00000000 00000000 00000001 01010110- il numero 342 in una variabile di tipo int in java 11111111 11111111 11111110 10101001- il risultato dell'espressione ~342 in java Proviamo a fare questo in pratica:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(~x));
   }
}
Uscita console:
11111111111111111111111010101001
  • &— operatore bit a bit “AND”

Come puoi vedere, è scritto in modo abbastanza simile all'“AND” logico ( &&). L'operatore &&, come ricorderete, restituisce truesolo se entrambi gli operandi sono veri. Bitwise &funziona in modo simile: confronta due numeri bit per bit. Il risultato di questo confronto è il terzo numero. Ad esempio, prendiamo i numeri 277 e 432: 100010101 - il numero 277 in forma binaria 110110000 - il numero 432 in forma binaria Successivamente, l'operatore &confronta il primo bit del numero superiore con il primo bit di quello inferiore. Trattandosi di un operatore “AND”, il risultato sarà uguale a 1 solo se entrambi i bit sono uguali a 1. In tutti gli altri casi, il risultato sarà 0. 100010101 & 110110000 _______________ 100010000 - risultato del lavoro & Confrontiamo prima i primi bit di due numeri tra loro, poi il secondo bit, il terzo, ecc. Come puoi vedere, solo in due casi entrambi i bit nei numeri erano uguali a 1 (il primo e il quinto bit). Il risultato di tutti gli altri confronti era 0. Pertanto, alla fine abbiamo ottenuto il numero 100010000. Nel sistema decimale corrisponde al numero 272. Controlliamo:
public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Uscita console:

272
  • |- “OR” bit per bit. Il principio di funzionamento è lo stesso: confrontiamo due numeri poco a poco. Solo ora se almeno uno dei bit è uguale a 1, il risultato sarà uguale a 1. Consideriamo gli stessi numeri: 277 e 432:
100010101 | 110110000 _______________ 110110101 - il risultato del lavoro | Qui il risultato è diverso: solo quei bit che erano zeri in entrambi i numeri sono rimasti zeri. Il risultato del lavoro è il numero 110110101. Nel sistema decimale corrisponde al numero 437. Controlliamo:
public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Uscita console:

437
Abbiamo contato tutto correttamente! :)
  • ^- OR esclusivo bit per bit (noto anche come XOR)
Non abbiamo mai incontrato un operatore del genere prima. Ma non c’è nulla di complicato in questo. Sembra un normale "o". La differenza è una: il "or" ordinario restituisce truese almeno un operando è vero. Ma non necessariamente uno – se ci sono entrambi true– allora il risultato true. Ma l'esclusivo "o" ritorna truesolo se uno degli operandi è vero. Se entrambi gli operandi sono veri, verrà restituito un "or" regolare true("almeno uno è vero"), ma un or esclusivo restituirà false. Ecco perché si chiama esclusivo. Conoscendo il principio delle precedenti operazioni bit a bit, probabilmente puoi facilmente eseguire tu stesso l'operazione 277 ^ 432. Ma cerchiamo di capirlo meglio insieme ancora una volta :) 100010101 ^ 110110000 _______________ 010100101 - il risultato del lavoro ^ Ecco il nostro risultato. I bit uguali in entrambi i numeri restituivano 0 (la formula “uno di” non funzionava). Ma quelli che formavano una coppia 0-1 o 1-0 alla fine si sono trasformati in un'unità. Di conseguenza, abbiamo ottenuto il numero 010100101. Nel sistema decimale corrisponde al numero 165. Vediamo se abbiamo calcolato correttamente:
public class Main {

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

165
Super! Tutto è esattamente come pensavamo :) Ora è il momento di familiarizzare con le operazioni chiamate bit shift. Il nome, in linea di principio, parla da solo. Prenderemo un numero e sposteremo i suoi bit a sinistra e a destra :) Vediamo come appare:

Spostati a sinistra

Lo spostamento a sinistra dei bit è indicato dal segno << Esempio:
public class Main {

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

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
In questo esempio, il numero x=64è chiamato valore. Sono le sue parti che sposteremo. Sposteremo i bit a sinistra (questo può essere determinato dalla direzione del segno <<) Nel sistema binario, il numero 64 = 1000000 Il numero y=3si chiama quantità. La quantità risponde alla domanda “di quanti bit a destra/sinistra devono essere spostati i bit di un numero x?” Nel nostro esempio li spostiamo di 3 bit a sinistra. Per rendere più chiaro il processo di cambiamento, guardiamo l'immagine. Nel nostro esempio utilizziamo numeri di tipo int. Intoccupano 32 bit di memoria del computer. Ecco come appare il nostro numero originale 64: Operazioni bit a bit - 2E ora, nel senso letterale della parola, prendiamo ciascuno dei nostri bit e lo spostiamo a sinistra di 3 celle: Operazioni bit a bit - 3Questo è ciò che abbiamo ottenuto. Come puoi vedere, tutti i nostri bit si sono spostati e sono stati aggiunti altri 3 zeri dall'esterno dell'intervallo. 3 - perché ci siamo spostati di 3. Se ci siamo spostati di 10, verrebbero aggiunti 10 zeri. Quindi l’espressione x << ysignifica “sposta i bit di un numero хy celle verso sinistra”. Il risultato della nostra espressione è stato il numero 1000000000, che nel sistema decimale è uguale a 512. Controlliamo:
public class Main {

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

       int z = (x << y);
       System.out.println(z);
   }
}
Uscita console:

512
Giusto! In teoria, i bit possono essere spostati indefinitamente. Ma poiché abbiamo il numero int, ci sono solo 32 celle disponibili. Di questi, 7 sono già occupati dal numero 64 (1.000.000). Pertanto, se effettuiamo, ad esempio, 27 spostamenti a sinistra, la nostra unica unità andrà fuori portata e “sovrascriverà”. Rimarranno solo gli zeri!
public class Main {

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

       int z = (x << y);
       System.out.println(z);
   }
}
Uscita console:

0
Come ci aspettavamo, quella è andata oltre le celle a 32 bit ed è scomparsa. Abbiamo ottenuto un numero a 32 bit composto solo da zeri. Operazioni bit a bit - 4Naturalmente nel sistema decimale corrisponde a 0. Una regola semplice per ricordare lo spostamento a sinistra: ad ogni spostamento a sinistra il numero viene moltiplicato per 2. Proviamo ad esempio a calcolare il risultato dell'espressione senza immagini con bit 111111111 << 3 . per moltiplicare tre volte il numero 111111111 per 2. Di conseguenza, otteniamo 888888888. Scriviamo il codice e controlliamolo:
public class Main {

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

888888888

Spostamenti a destra

Sono indicati dal cartello >>. Fanno la stessa cosa, solo nella direzione opposta! :) Non reinventiamo la ruota e proviamo a farlo con lo stesso numero intero 64.
public class Main {

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

       int z = (x >> y);
       System.out.println(z);
   }
}
Operazioni bit a bit - 5Operazioni bit a bit - 6Come risultato dello spostamento di 2 a destra, i due zeri estremi del nostro numero sono usciti dall'intervallo e sono stati cancellati. Abbiamo ottenuto il numero 10000, che nel sistema decimale corrisponde al numero 16. Output sulla console:

16
Una semplice regola per ricordare gli spostamenti a destra: ogni spostamento a destra divide per due, scartando l'eventuale resto. Ad esempio, 35 >> 2 significa che dobbiamo dividere 35 per 2 2 volte, scartando il resto 35/2 = 17(scartando resto 1) 17:2 = 8(scartando resto 1) Il totale 35 >> 2dovrebbe essere uguale a 8. Controlla:
public class Main {

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

8

Precedenza delle operazioni in Java

Mentre scrivi o leggi il codice, ti imbatterai spesso in espressioni in cui vengono eseguite più operazioni contemporaneamente. È molto importante capire in quale ordine verranno eseguiti, altrimenti il ​​risultato potrebbe essere inaspettato. Poiché in Java ci sono molte operazioni, sono state tutte separate in una tabella speciale:

Precedenza dell'operatore

Operatori Precedenza
suffisso expr++ expr--
unario ++expr --expr +expr ~ !
Moltiplicativo * / %
additivo + -
spostare << >> >>>
relazionale < > <= >=istanza di
uguaglianza == !=
bit per bit AND &
OR esclusivo bit per bit ^
OR inclusivo bit per bit |
E logico &&
OR logico ||
ternario ? :
Incarico = += -= *= /= %= &= ^= |= <<= >>= >>>=
Tutte le operazioni vengono eseguite da sinistra a destra, ma tenendo conto della loro priorità. Se ad esempio scriviamo: int x = 6 - 4/2; prima verrà eseguita l'operazione di divisione (4/2). Sebbene sia la seconda in fila, ha la priorità più alta. Parentesi quadre o parentesi quadre modificano qualsiasi priorità al massimo. Probabilmente te lo ricordi da scuola. Ad esempio, se li aggiungi a un'espressione: int x = (6 - 4)/2; la sottrazione verrà eseguita per prima, poiché viene calcolata tra parentesi. L'operatore logico ha &&una priorità piuttosto bassa, come si può vedere dalla tabella. Pertanto, molto spesso verrà eseguito per ultimo. Ad esempio: boolean x = 6 - 4/2 > 3 && 12*12 <= 119; questa espressione verrebbe eseguita in questo modo:
  • 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;
  • Successivamente verranno eseguiti gli operatori di confronto:

    4 > 3 = true

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

    boolean x = true && false;
  • Infine, verrà eseguito l'ultimo operatore &&.

    boolean x = true && false;

    boolean x = false;

    L'operatore di addizione ( +), ad esempio, ha una precedenza maggiore rispetto all'operatore di confronto !=(“non uguale”);

    Pertanto nell'espressione:

    boolean x = 7 != 6+1;

    prima verrà eseguita l'operazione 6+1, poi il controllo 7!=7 (falso), e alla fine il risultato verrà assegnato alla falsevariabile x. L'assegnazione generalmente ha la priorità più bassa di tutte le operazioni: guarda la tabella.

Uff! La nostra conferenza è stata lunga, ma ce l'hai fatta! Se non comprendi appieno alcune parti di questa e delle lezioni precedenti, non preoccuparti, toccheremo questi argomenti più di una volta in futuro. Ecco alcuni link utili per te:
  • Operatori logici - Lezione JavaRush sulle operazioni logiche. Non li troveremo presto, ma puoi leggerli adesso, non ci sarà alcun danno
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION