1. Bitvis vänsterväxling

Java har också 3 bitvisa skiftoperatorer : Om du verkligen behöver det kan du helt enkelt flytta alla bitar i ett nummer flera positioner åt vänster eller höger.

För att flytta bitarna i ett nummer åt vänster behöver du den bitvisa vänstra skiftoperatorn . Så här är det skrivet:

a << b

Var aär talet vars bitar skiftas, och bär ett tal som anger hur många gånger bitarna i numret ska flyttas aåt vänster. Under denna operation är de låga ordningens bitar som läggs till till höger nollor.

Exempel:

Exempel Resultat
0b00000011 << 1
0b00000110
0b00000011 << 2
0b00001100
0b00000011 << 5
0b01100000
0b00000011 << 20
0b001100000000000000000000

Att flytta en siffra åt vänster har samma effekt som att multiplicera ett tal med 2.

Vill du multiplicera ett tal med 16? 16 är samma som 2 4 . Så du flyttar siffran fyra siffror åt vänster


2. Växla bitvis åt höger

Bits kan också flyttas åt höger. För att göra detta, använd den bitvisa högerväxlingsoperatören . Så här är det skrivet:

a >> b

Var aär antalet vars bitar skiftas, och bär antalet gånger för att skifta bitarna i numret aåt höger.

Exempel:

Exempel Resultat
0b11000011 >> 1
0b01100001
0b11000011 >> 2
0b00110000
0b11000011 >> 5
0b00000110
0b11000011 >> 20
0b00000000

Att flytta en siffra åt höger har samma effekt som att dividera ett tal med 2.

Under denna operation är de högordningsbitar som läggs till till vänster nollor, men inte alltid !

Viktig!

Biten längst till vänster i ett tecken med tecken kallas teckenbiten : om talet är positivt är det 0; men om talet är negativt är denna bit 1.

Vid förskjutning av bitarna i ett tal åt höger skulle värdet på teckenbiten vanligtvis också skifta och talets tecken skulle gå förlorat. Följaktligen, för negativa tal (där biten längst till vänster är 1), får denna bit specialbehandling. När bitarna i ett tal flyttas åt höger läggs a 0till till vänster om biten längst till vänster var , 0och a 1läggs till till vänster om biten längst till vänster var 1.

Men i exemplet ovan verkar det inte vara resultatet. Varför? Eftersom heltalsliteraler är ints och  betyder faktiskt . Det vill säga, biten längst till vänster är noll.0b111111110b00000000000000000000000011111111

Många programmerare är frustrerade över detta högerförskjutningsbeteende och skulle föredra att numret alltid är utfyllt med nollor. Så Java lade till ytterligare en högerskiftsoperatör .

Så här är det skrivet:

a >>> b

Var a är antalet vars bitar skiftas, och b  är antalet gånger för att skifta bitarna i numret aåt höger. Denna operator lägger alltid till nollor till vänster, oavsett det ursprungliga värdet på teckenbiten för talet a.



3. Arbeta med flaggor

Programmerare skapade ett nästan helt nytt studieområde på basis av bitvis och skiftoperationer: att arbeta med flaggor.

När datorer hade väldigt lite minne var det mycket populärt att stoppa in mycket information i ett enda nummer. Ett nummer behandlades som en array av bitar: en int är 32 bitar och en long är 64 bitar.

Du kan skriva mycket information i ett sådant nummer, särskilt om du behöver lagra logiska ( trueeller false) värden. En singel longär som en booleanarray som består av 64 element. Dessa bitar kallades flaggor och manipulerades med följande operationer:

  • sätta flaggan
    (gör en specifik bit lika med 1)
  • återställ flaggan
    (gör en specifik bit lika med 0)
  • kontrollera flaggan
    (kontrollera värdet på en specifik bit)

Och här är hur det går till med bitvisa operatorer.

Att sätta en flagga

För att ställa in en specifik bit till 1måste du utföra en bitvis ELLER-operation mellan talet vars bit du vill ställa in och ett speciellt skapat nummer, där bara den biten är 1.

Anta till exempel att du har numret 0b00001010och att du måste ställa in den 5:e biten till 1. I så fall måste du:

0b00001010 | 0b00010000 = 0b00011010

Om den 5:e biten redan hade ställts in på ett, skulle ingenting ha förändrats.

I allmänhet kan operationen att sätta en flagga skrivas enligt följande

a | (1 << b)

Var a är numret vars bit kommer att ställas in på 1. Och b är bitens position som ska ställas in. Att använda vänster växlingsoperatör är superbekvämt här, eftersom du direkt kan se vilken bit vi arbetar med.

Återställa en flagga

För att återställa en specifik bit (dvs. ställa in den till 0) utan att störa andra bitar, måste du utföra en &operation mellan talet vars bit du vill återställa (dvs. ställa in till ) 0och ett speciellt skapat nummer, där alla bitar är lika med 1utom för den bit du vill återställa.

Anta till exempel att du har numret 0b00001010och att du måste ställa in den 4:e biten till 0. I så fall måste du:

0b00001010 & 0b11110111 = 0b00000010

Om den 4:e biten redan hade ställts in på noll, skulle ingenting ha förändrats.

I allmänhet kan operationen att återställa en flagga skrivas enligt följande

a & ~(1 << b)

Var a är numret vars bit kommer att återställas till 0. Och b är bitens position som ska rensas.

För att få ett tal där alla bitar är 1utom den vi vill ska vara noll, flyttar vi först 1 b  positioner åt vänster och använder sedan den bitvisa NOToperatorn för att invertera resultatet.

Kontrollerar en flagga

Förutom att ställa in eller återställa en specifik flagga behöver du ibland bara kontrollera om en given flagga är satt, dvs om en viss bit är lika med 1. Detta är ganska lätt att göra med bitvis &.

Anta till exempel att du behöver kontrollera om den 4:e biten är inställd 1på numret 0b00001010. Då måste du göra så här:

if ( (0b00001010 & 0b00001000) == 0b00001000 )

I allmänhet kan operationen att kontrollera en flagga skrivas enligt följande

(a & (1 << b)) == (1 << b)

Var a är numret vars bit kontrolleras. Och b är bitens position som ska kontrolleras.


4. Kryptering

Den bitvisa XORoperationen används ofta av programmerare för enkel kryptering. I allmänhet ser sådan kryptering ut så här:

result = number ^ password;

Var number finns data vi vill kryptera, password är ett speciellt nummer som används som "lösenord" för data, och result är det krypterade numret.

number == (number ^ password) ^ password;

Det viktiga här är att när XORoperatorn appliceras på ett nummer två gånger, producerar den det ursprungliga numret, oavsett "lösenordet".

För att återhämta dig number från encrypted result, behöver du bara utföra operationen igen:

original number = result ^ password;

Exempel:

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));
   }
}