Java-bit­ti­koh­tai­sil­la ope­raat­to­reil­la voit ma­ni­pu­loi­da yk­sit­täi­siä bittejä ha­lua­mal­la­si tavalla. Seitsemän ope­raat­to­ria on ra­ken­net­tu samalla tavalla ja ne nou­dat­ta­vat helposti opittavia kiinteitä sääntöjä.

Mitä ovat bit­ti­ta­son ope­raat­to­rit ja mihin niitä käytetään?

Java-ope­raat­to­rit ovat tärkeä työkalu oh­jel­moin­ti­kie­len käytössä. Monien muiden mah­dol­li­suuk­sien ja toi­min­to­jen lisäksi ne antavat sinulle mah­dol­li­suu­den ma­ni­pu­loi­da pienimpiä mah­dol­li­sia tie­to­yk­si­köi­tä: bittejä. Biteillä (bi­nää­ri­lu­vuil­la) on oma nu­me­ro­jär­jes­tel­mä, joka perustuu arvoihin 0 ja 1. Jos haluat kysellä bi­nää­riar­vo­ja bitti ker­ral­laan, tarvitset Java-kielessä bit­ti­koh­tai­sen ope­raat­to­rin. Voit soveltaa tätä nu­mee­ri­siin tie­to­tyyp­pei­hin (byte, char, int, short, long).

Vaikka et tarvitse tätä toimintoa päi­vit­täin, se voi olla hyö­dyl­li­nen monissa ti­lan­teis­sa. Se voi olla kätevä esi­mer­kik­si, jos haluat säästää tilaa tietojen muun­ta­mi­ses­sa, jos haluat käyttää XOR-ope­raat­to­ria tai jos haluat vain muuttaa bittiä. Ne ovat myös kaikkien kor­keam­pien pii­ri­toi­min­to­jen perusta. Siksi on tärkeää ymmärtää Java-bit­ti­toi­min­to­jen pe­rus­o­mi­nai­suu­det.

Mitkä Java-bit­ti­ta­son ope­raat­to­rit ovat olemassa?

Java-kielessä on yhteensä seitsemän erilaista bit­ti­ta­son ope­raat­to­ria. Jotta saisimme kattavan kä­si­tyk­sen, aloitamme ope­ran­deis­ta a ja b.

  • ~ (bit­ti­ta­son NOT, komple­ment­ti): Tämä ope­raat­to­ri kääntää bitit. 0 muuttuu 1:ksi ja 1 muuttuu 0:ksi.
  • & (bit­ti­ta­son AND): Tämä ope­raat­to­ri tuottaa tu­lok­sek­si 1, jos molemmat operandit ovat 1. Muussa ta­pauk­ses­sa tu­lok­sek­si tulee 0.
  • | (bit­ti­ta­son OR): Tämä ope­raat­to­ri tuottaa 1:n, jos jom­pi­kum­pi ope­ran­deis­ta on myös 1.
  • ^ (XOR tai bit­ti­ta­son eksklusii­vi­nen OR): Tämä ope­raat­to­ri tuottaa 0:n, jos mo­lem­mil­la ope­ran­deil­la on sama arvo. Muussa ta­pauk­ses­sa se tuottaa 1:n.
  • << (vasen siirto): Tämä ope­raat­to­ri siirtää operandin a va­sem­mal­le b paikkaa. Jos tämä aiheuttaa tyhjiä paikkoja, ne täytetään nollilla.
  • >> (oikealle siirto merkin kanssa, arit­meet­ti­nen): Tämä ope­raat­to­ri siirtää kaikki a: n bitit b paikkaa oikealle. Jos suurimman arvon omaava bitti oli asetettu ennen suo­rit­ta­mis­ta, se pysyy ase­tet­tu­na myös jäl­keen­päin. Ne­ga­tii­vi­set luvut pysyvät ne­ga­tii­vi­si­na.
  • >>>> (mer­kit­se­mä­tön oikealle siir­tä­mi­nen, looginen): Tämä ope­raat­to­ri siirtää a: n bitit b paikkaa oikealle. Vä­li­lyön­nit täytetään aina nollilla.

Bit­ti­ta­son NOT

Java-bit­ti­koh­tai­sen ope­raat­to­rin bit­ti­koh­tai­nen NOT esitetään tilde-merkillä (~). Se kumoaa kaikki bitit, muut­ta­mal­la nollat ykkösiksi ja ykköset nolliksi. Otetaan esi­mer­kik­si luku 20. Bi­nää­ri­muo­dos­sa se näyttää tältä: 10100. Jos so­vel­lam­me bit­ti­ta­son NOT-ope­raat­to­ria, jokainen luvun bitti vaihtuu: 10100 muuttuu 01011:ksi. Tämä on lausek­keen ~20 arvo. Jos muunnamme tämän bi­nää­ri­lu­vun takaisin de­si­maa­li­lu­vuk­si, saamme arvon -21. Jos haluat kokeilla tätä prosessia Java-kielellä, kirjoita seuraava koodi ja Java-komento System.out.println tu­los­taak­se­si tuloksen.

public class Main {
	public static void main(String[] args) {
	int value1 = 20;
	System.out.println(~value1);
}
}
java

Jos olet syöttänyt kaikki tiedot oikein, tuloksena pitäisi näkyä ”-21”.

Bit­ti­ta­son AND

Bit­ti­ta­son AND vertaa kahta lukua bi­nää­ri­muo­dos­sa bitti ker­ral­laan. En­sim­mäi­sen luvun en­sim­mäi­nen bitti verrataan toisen luvun en­sim­mäi­seen bittiin, toinen bitti toiseen bittiin ja niin edelleen. Jos molemmat bitit ovat 1, tuloksena on 1. Jos näin ei ole (molemmat bitit ovat 0 tai toinen biteistä on 0), tuloksena on 0. Alla olevassa esi­mer­kis­sä tar­kas­te­lem­me kahta de­si­maa­li­lu­kua 18 ja 25. Bi­nää­ri­lu­ku­na 18 on 10010 ja 25 bi­nää­ri­muo­dos­sa on 11001. Ver­tail­laan nyt näitä kahta lukua ja mää­ri­te­tään niistä kolmas luku.

18 = 10010 25 = 11001

Nu­me­roi­den kaksi en­sim­mäis­tä bittiä ovat molemmat 1, joten tuloksena oleva numero alkaa myös 1:llä. Numero 25:n toinen bitti on myös 1, mutta numeron 18 toinen bitti on 0, joten kolmannen numeron numero on 0. Kun olemme käyneet läpi molemmat numerot bitti bittiä, saamme bi­nää­ri­lu­vun 10000. Jos muunnamme tämän de­si­maa­li­lu­vuk­si, tulos on 16.

Koodi näyttää tältä:

public class Main {
	public static void main(String[] args) {
	System.out.println(18&25);
}
}
java

Konsolin tulosteen tulisi olla 16.

Bit­ti­ta­son OR

Java-ope­raat­to­ri bitwise OR vertaa myös kahta lukua bitti bitiltä. Tässä ta­pauk­ses­sa kuitenkin vain toisen operandin arvon on oltava 1, jotta tulos on 1. Jos otamme edellisen esimerkin luvut, se näyttää tältä:

18 = 10010 25 = 11001

Koska kaikki bitit paitsi kolmas numero si­säl­tä­vät vähintään yhden 1:n, tuloksena oleva luku on: 11011. Muun­net­tu­na saamme 27.

Tässä on esimerkki koodina:

public class Main {
	public static void main(String[] args) {
	System.out.println(18|25);
}
}
java

XOR

XOR tai bit­ti­ta­son eksklusii­vi­nen OR (^) on sa­man­lai­nen kuin bit­ti­ta­son OR. Bit­ti­ta­son OR:n ta­pauk­ses­sa yhden tai molempien ope­ran­dien on oltava 1, jotta tuloksena saadaan 1. XOR:n ta­pauk­ses­sa tuloksena saadaan 1 vain, jos täs­mäl­leen toinen arvoista on 1. Jotta XOR:n toiminta tulisi paremmin selväksi, kat­so­taan­pa esi­merk­kiä:

18 = 10010 25 = 11001

Kahden en­sim­mäi­sen bitin arvo on 1, joten tämän Java-bittien ope­raat­to­rin avulla tulos on 0. 18:n toinen bitti on 0, mutta 25:n toinen bitti on 1. Tuloksena on arvo 1. Jos jatkamme, saamme luvun 01011. De­si­maa­li­muo­dos­sa tämä on 11.

Tässä on koodi:

public class Main {
	public static void main(String[] args) {
	System.out.println(18^25);
}
}
java

Vasen siirtymä

Vasen siirto siirtää arvon a bittejä va­sem­mal­le etäi­syy­del­lä b. Tuloksena syntyvät tyhjät kohdat täytetään nollilla. Tämä on helppo ymmärtää, kun tar­kas­tel­laan int-arvoa, joka vie muistista 32 bittiä. Otetaan j älleen luku 20 tai 10010 ja siir­re­tään sitä b-arvolla 2, jolloin saadaan c-arvo 1001000. Loppuun lisätään kaksi nollaa. 1001000 vastaa de­si­maa­li­lu­kua 72.

Tässä on prosessin koodi:

public class Main {
	public static void main(String[] args) {
	int a = 20;
	int b = 2;
	int c = (a << b);
	System.out.println(c);
}
}
java

Oikealle siir­tä­mi­nen merkin kanssa

Oikealle siir­tä­mi­nen toimii päin­vas­toin. Tässä arvosta a siir­re­tään bittejä oikealle arvolla b, mikä tuottaa arvon c. Tuloksena viimeiset bitit jäävät pois. Jos siirrämme 20 tai 10010 kaksi paikkaa oikealle, tulos on 100 tai 4.

Tässä on koodi:

public class Main {
	public static void main(String[] args) {
	System.out.println(20 >> 2);
}
}
java

On tärkeää huomata, että jos a on po­si­tii­vi­nen luku, välit täytetään nollalla. Jos se on ne­ga­tii­vi­nen, välit korvataan ykkösellä.

Oikealle siir­tä­mi­nen ilman merkkiä

Pe­ri­aat­tees­sa Java-bit­ti­ta­son ope­raat­to­ri oikealle ilman merkkiä (>>>) toimii samalla tavalla. Ainoa ero on, että oikealle siir­tä­mi­sen va­sem­mal­le puolelle syntyvät välit täytetään aina nollilla. Tämä johtaa aina po­si­tii­vi­seen lukuun, vaikka alkuarvo olisi ne­ga­tii­vi­nen. 2d0e3502501316d60de09e1727bc6aba

Siirry pää­va­lik­koon