1. Bitvis venstreforskyvning

Java har også 3 bitvise skiftoperatorer : Hvis du virkelig trenger det, kan du ganske enkelt flytte alle bitene til et tall flere posisjoner til venstre eller høyre.

For å flytte bitene til et tall til venstre, trenger du den bitvise venstre skiftoperatoren . Slik er det skrevet:

a << b

Hvor aer tallet hvis biter blir forskjøvet, og ber et tall som indikerer hvor mange ganger bitene til tallet skal forskyves atil venstre. Under denne operasjonen er bitene av lav orden som legges til til høyre, null.

Eksempler:

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

Å flytte ett siffer til venstre har samme effekt som å multiplisere et tall med 2.

Vil du multiplisere et tall med 16? 16 er det samme som 2 4 . Så du flytter tallet 4 sifre til venstre


2. Bitvis skift til høyre

Bits kan også flyttes til høyre. For å gjøre dette, bruk bitvis høyre skiftoperator . Slik er det skrevet:

a >> b

Hvor aer tallet hvis biter blir forskjøvet, og ber antall ganger bitene til tallet skal flyttes atil høyre.

Eksempler:

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

Å flytte ett siffer til høyre har samme effekt som å dele et tall med 2.

Under denne operasjonen er bitene av høy orden som legges til til venstre, null, men ikke alltid !

Viktig!

Biten lengst til venstre i et fortegnet tall kalles fortegnsbiten : hvis tallet er positivt, er det 0; men hvis tallet er negativt, er denne biten 1.

Når bitene til et tall forskyves til høyre, vil verdien av fortegnsbiten vanligvis også skifte og fortegnet til tallet vil gå tapt. Følgelig, for negative tall (hvor biten lengst til venstre er 1), får denne biten spesialbehandling. Når du flytter bitene til et tall til høyre, 0legges a til venstre hvis biten lengst til venstre var 0, og a 1legges til venstre hvis biten lengst til venstre var 1.

Men i eksemplet ovenfor ser det ikke ut til at det er resultatet. Hvorfor? Fordi heltalls bokstaver er ints, og  betyr faktisk . Det vil si at biten lengst til venstre er null.0b111111110b00000000000000000000000011111111

Mange programmerere er frustrerte over denne høyreskiftadferden og foretrekker at tallet alltid er polstret med nuller. Så Java la til en annen høyreskiftoperatør .

Slik er det skrevet:

a >>> b

Hvor a er tallet hvis biter blir forskjøvet, og b  er antall ganger bitene til tallet skal flyttes atil høyre. Denne operatoren legger alltid til nuller til venstre, uavhengig av den opprinnelige verdien av fortegnsbiten til tallet a.



3. Arbeide med flagg

Programmerere opprettet et nesten helt nytt fagfelt på grunnlag av bitvise og skiftoperasjoner: arbeid med flagg.

Når datamaskiner hadde svært lite minne, var det svært populært å stappe mye informasjon inn i et enkelt nummer. Et tall ble behandlet som en rekke biter: en int er 32 biter, og en long er 64 biter.

Du kan skrive mye informasjon i et slikt tall, spesielt hvis du trenger å lagre logiske ( trueeller false) verdier. En singel longer som en booleanmatrise bestående av 64 elementer. Disse bitene ble kalt flagg og ble manipulert ved hjelp av følgende operasjoner:

  • sette flagg
    (gjør en bestemt bit lik 1)
  • tilbakestill flagg
    (gjør en bestemt bit lik 0)
  • sjekk flagget
    (sjekk verdien av en bestemt bit)

Og her er hvordan det gjøres med bitvise operatører.

Sette et flagg

For å sette en spesifikk bit til 1, må du utføre en bitvis ELLER-operasjon mellom tallet hvis bit du vil sette og et spesiallaget tall, der bare den biten er 1.

Anta for eksempel at du har nummeret 0b00001010og at du må sette den 5. biten til 1. I så fall må du:

0b00001010 | 0b00010000 = 0b00011010

Hvis den 5. biten hadde blitt satt til én allerede, ville ingenting ha endret seg.

Generelt kan operasjonen med å sette et flagg skrives som følger

a | (1 << b)

Hvor a er tallet hvis bit vil bli satt til 1. Og b er posisjonen til bittet som skal stilles inn. Å bruke venstre skiftoperatør er super praktisk her, siden du umiddelbart kan se hvilken bit vi jobber med.

Tilbakestille et flagg

For å tilbakestille en spesifikk bit (dvs. sette den til 0) uten å forstyrre andre biter, må du utføre en &operasjon mellom nummeret hvis bit du vil tilbakestille (dvs. satt til 0) og et spesiallaget tall, der alle bitene er like 1unntatt for biten du vil tilbakestille.

Anta for eksempel at du har nummeret 0b00001010og at du må sette den fjerde biten til 0. I så fall må du:

0b00001010 & 0b11110111 = 0b00000010

Hvis den fjerde biten allerede hadde blitt satt til null, ville ingenting ha endret seg.

Generelt kan operasjonen med å tilbakestille et flagg skrives som følger

a & ~(1 << b)

Hvor a er nummeret hvis bit vil bli tilbakestilt til 0. Og b er posisjonen til biten som skal ryddes.

For å få et tall der alle bitene er 1unntatt den vi ønsker skal være null, skifter vi først 1 b  posisjoner til venstre, og bruker deretter den bitvise NOToperatoren for å invertere resultatet.

Sjekker et flagg

I tillegg til å sette eller tilbakestille et spesifikt flagg, trenger du noen ganger bare å sjekke om et gitt flagg er satt, dvs. om en viss bit er lik 1. Dette er ganske enkelt å gjøre med litt &.

Anta for eksempel at du må sjekke om den fjerde biten er satt til 1i tallet 0b00001010. Da må du gjøre dette:

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

Generelt kan operasjonen med å sjekke et flagg skrives som følger

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

Hvor a er nummeret hvis bit blir sjekket. Og b er posisjonen til bittet som skal sjekkes.


4. Kryptering

Den bitvise XORoperasjonen brukes ofte av programmerere for enkel kryptering. Generelt ser slik kryptering slik ut:

result = number ^ password;

Hvor number er dataene vi ønsker å kryptere, password er et spesialnummer som brukes som "passord" for dataene, og result er det krypterte nummeret.

number == (number ^ password) ^ password;

Det viktige her er at når operatoren XORbrukes på et tall to ganger, produserer den det opprinnelige tallet, uavhengig av "passordet".

For å gjenopprette number fra encrypted result, trenger du bare å utføre operasjonen på nytt:

original number = result ^ password;

Eksempel:

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