I dagens lektion kommer vi att bekanta oss med Java Bitwise Operators och överväga exempel på hur man arbetar med dem. Du är förmodligen bekant med ordet "bit". Om inte, låt oss komma ihåg vad det betyder :) Lite är den minsta informationsenheten i en dator. Dess namn kommer från binära siffror . En bit kan uttryckas med ett av två tal: 1 eller 0. Det finns ett speciellt binärt talsystem baserat på ettor och nollor. Vi kommer inte att fördjupa oss i en matematisk djungel här. Vi noterar bara att alla tal i Java kan konverteras till binär form. För att göra detta måste du använda omslagsklasserna.
Bitvisa operatorer - 1
Så här kan du till exempel göra detta för en int :

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Konsolutgång: 101010110 1010 10110 (jag lade till mellanslag för att göra det lättare att läsa) är siffran 342 i decimalsystemet. Vi har faktiskt delat upp det här antalet i enskilda bitar: nollor och ettor. Operationer som utförs på bitar kallas bitvis .
  • ~ - bitvis INTE.
Den här operatorn är väldigt enkel: den passerar över varje bit av vårt nummer och vänder biten: nollor blir ettor och ettor blir nollor. Om vi ​​tillämpar det på vårt nummer 342, så händer det här: 101010110 är 342 representerat som ett binärt tal 010101001 är värdet på uttrycket ~342 Låt oss försöka omsätta detta i praktiken:

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(~x);
   }
}
Konsolutgång: 169 169 är vårt resultat ( 010101001 ) i det välbekanta decimalsystemet :)
  • & - bitvis OCH
Som du kan se ser det ganska likt ut det logiska OCH ( && ). Operatorn && , minns du, returnerar bara sant om båda operanderna är sanna. Bitvis & fungerar på liknande sätt: den jämför två tal bit för bit. Jämförelsen ger ett tredje tal. Låt oss till exempel ta siffrorna 277 och 432: 110110000 är 277 representerat som ett binärt tal 1000101011 är 432 representerat som ett binärt tal. Därefter jämför operatorn & den första biten av det övre talet med den första biten av det nedersta talet. Eftersom detta är en AND-operator blir resultatet 1 endast om båda bitarna är 1. I alla andra fall är resultatet 0. 100010101 && operator Först jämför vi de första bitarna av de två talen, sedan de andra bitarna, sedan den tredje och så vidare. Som du kan se, i endast två fall är båda motsvarande bitar i talen lika med 1 (den första och femte biten). Alla andra jämförelser gav 0:or. Så till slut fick vi talet 10001000. I decimalsystemet motsvarar det talet 272. Låt oss kolla:

public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Konsolutgång: 272
  • | - bitvis ELLER.
Denna operator fungerar på samma sätt: jämför två tal bit för bit. Först nu om åtminstone en av bitarna är 1, så är resultatet 1. Låt oss titta på samma siffror (277 och 432): 100010101 | 110110000 _______________ 110110101 - resultat av | operator Här får vi ett annat resultat: de enda bitarna som förblir nollor är de bitar som var nollor i båda talen. Resultatet är talet 110110101. I decimalsystemet motsvarar det talet 437 Låt oss kontrollera:

public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Konsoleffekt: 437 Vi har beräknat allt korrekt! :)
  • ^ - bitvis XOR (exklusiv ELLER)
Vi har ännu inte stött på den här operatören. Men det är inget komplicerat med det. Det liknar den vanliga OR-operatören. Det finns en skillnad: det vanliga ELLER returnerar sant om minst en operand är sann. Men det behöver inte vara en: om båda operanderna är sanna är resultatet sant. Men exklusiv OR returnerar bara sant om exakt en av operanderna är sann. Om båda operanderna är sanna, returnerar det vanliga ELLER sant ("minst ett sant"), men XOR returnerar falskt. Det är därför det kallas exklusivt OR. Genom att veta hur de tidigare bitvisa operatorerna fungerar kan du förmodligen enkelt räkna ut 277 ^ 432. Men låt oss gräva i det tillsammans en gång till :) 100010101 ^ 110110000 _______________ 010100101 - resultatet av ^operatör Det är vårt resultat. De bitar som var desamma i båda siffrorna ger en 0 (vilket betyder att "endast en"-testet misslyckades). Men bitarna som bildade ett 0-1 eller 1-0 par blev ettor. Vårt resultat är talet 010100101. I decimalsystemet motsvarar det talet 165. Låt oss se om våra beräkningar är korrekta:

public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Konsolutgång: 165 Super! Allt är precis som vi tänkt oss :) Nu är det dags att bekanta sig med bitskiftsoperatörer. Namnet talar för sig självt. Vi tar ett nummer och flyttar dess bitar åt vänster eller höger :) Låt oss se hur det ser ut:

Växla åt vänster

En förskjutning av bitar till vänster indikeras med << Här är ett exempel:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
I det här exemplet kallas talet x = 64 för värdet. Det är bitarna av värdet som vi kommer att flytta. Vi flyttar bitarna åt vänster (du kunde ha gissat detta med riktningen för <<- operatorn) I det binära systemet kallas talet 64 = 1000000 Talet y = 3 kallas skiftavstånd. Skiftavståndet anger hur många bitar till höger/vänster du vill flytta bitarna av talet x I vårt exempel flyttar vi dem 3 bitar åt vänster. För att se skiftprocessen tydligare, titta på bilden. I det här exemplet använder vi int s. Ints upptar 32 bitar i datorns minne. Så här ser vårt ursprungliga nummer 64 ut:
Bitvisa operatorer - 2
Och nu tar vi var och en av våra bitar och flyttar dem bokstavligen åt vänster med 3 ställen:
Bitvisa operatorer - 3
Ta en titt på vad vi har. Som du kan se har alla våra bitar skiftat, och ytterligare 3 nollor har lagts till från kanten av intervallet. Tre, eftersom vi skiftat med 3. Om vi ​​hade skiftat med 10 hade 10 nollor lagts till. Uttrycket x << y betyder alltså "skifta bitarna av talet x åt vänster med y-platser". Resultatet av vårt uttryck är talet 1000000000, vilket är 512 i decimalsystemet. Låt oss kolla:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Konsolutgång: 512 Spot on! Teoretiskt sett skulle bitarna kunna flyttas i det oändliga, men eftersom vårt nummer är en int , har vi bara 32 binära siffror tillgängliga. Av dessa är 7 redan upptagna av 64 (1000000). Därför, om vi flyttade 27 platser åt vänster, skulle vår enda gå utanför datatypens räckvidd och gå förlorad. Bara nollor skulle vara kvar!

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 26;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Konsolutgång: 0 Som förväntat flyttade den sig bortom de 32 tillgängliga bitarna och försvann. Vi avslutade med ett 32-bitars nummer som bara bestod av nollor.
Bitvisa operatorer - 4
Naturligtvis motsvarar detta 0 i decimalsystemet. Här är en enkel regel för att komma ihåg skift till vänster: För varje skift till vänster multipliceras talet med 2. Låt oss försöka beräkna följande uttryck utan bilder av bitar 111111111 << 3 Vi måste multiplicera talet 111111111 med 2 . Som ett resultat får vi 888888888. Låt oss skriva lite kod och kontrollera:

public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
Konsolutgång: 888888888

Växla åt höger

Denna operation betecknas med >> . Det gör samma sak, men åt andra hållet! :) Vi kommer inte att uppfinna hjulet på nytt. Låt oss prova det med samma int 64.

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 2;// Shift distance

       int z = (x >> y);
       System.out.println(z);
   }
}
Bitvisa operatorer - 5
Bitvisa operatorer - 6
Som ett resultat av en förskjutning till höger med 2, flyttas de två extrema nollorna i vårt nummer utanför intervallet och går förlorade. Vi får 10 000, vilket motsvarar siffran 16 i decimalsystemet Konsolutdata: 16 Här är en enkel regel för att komma ihåg skift till höger: Varje skift till höger divideras med två, och kasserar eventuell rest. Till exempel betyder 35 >> 2 att vi måste dividera 35 med 2 två gånger, och kassera resten 35/2 = 17 (kasta resten 1) 17/2 = 8 (kasta resten 1) I slutändan ska 35 >> 2 vara lika med 8. Låt oss kontrollera:

public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
Konsolutgång: 8

Operatörsföreträde i Java

När du skriver och läser kod hittar du ofta uttryck som kombinerar flera operationer. Det är mycket viktigt att förstå i vilken ordning de kommer att köras (annars kan du bli förvånad över resultatet) Eftersom Java har massor av operationer, har var och en av dem tilldelats en plats i en speciell tabell:

Operatörsföreträde

Operatörer Företräde
postfix expr++ expr--
unär ++expr --expr +expr ~ !
Multiplikativ * / %
tillsats + -
flytta << >> >>>
relationella < > <= >= instans av
jämlikhet == !=
bitvis OCH &
bitvis exklusivt ELLER ^
bitvis inklusive ELLER |
logiskt OCH &&
logiskt ELLER ||
ternär ? :
uppdrag = += -= *= /= %= &= ^= |= <<= >>= >>>=
Alla operationer utförs från vänster till höger, med hänsyn till deras företräde. Till exempel om vi skriver

int x  = 6 - 4/2;
sedan kommer delningsoperationen ( 4/2 ) att utföras först. Även om det kommer på andra plats, har det högre företräde. Parenteser och parenteser indikerar maximal företräde. Du kommer säkert ihåg det från skolan. Till exempel om du lägger till dem i uttrycket

int x  = (6 - 4)/2;
då utförs subtraktionen först, eftersom den är omgiven inom parentes. Företrädet för den logiska &&- operatorn är ganska låg (se tabellen), så den kommer vanligtvis att vara sist. Till exempel:

boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
Detta uttryck kommer att exekveras enligt följande:
  • 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;
Därefter körs jämförelseoperatorerna:
  • 4 > 3 = sant

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

boolean x = true && false;
Och slutligen kommer AND-operatorn ( && ) att köras sist.

boolean x = true && false;
boolean x = false;
Till exempel, operatorn addition( + ) har högre prioritet än jämförelseoperatorn != (inte lika); Därför i uttrycket

boolean x = 7 != 6+1;
6+1-operationen kommer att utföras först, sedan 7 != 7-kontrollen (som utvärderas till falsk), och slutligen tilldelningen av resultatet (falskt) till variabeln x (tilldelningen har i allmänhet den lägsta prioritet av alla operatorer ; se bordet). Puh! Det var en stor lektion, men du gjorde det! Om du inte helt förstod några av dessa eller tidigare lektioner, oroa dig inte. Vi kommer att beröra dessa ämnen mer än en gång i framtiden. Ett par CodeGym-lektioner om logiska och numeriska operationer. Vi kommer inte till dessa inom kort, men det skadar inte att du läser dem nu.