Hitri bitni in bitni premiki (s primeri)

V tej vadnici boste spoznali različne bitne operacije v Swiftu. Ti se uporabljajo za izračun bitne ravni v izrazu.

Bit se uporablja za označevanje binarne številke. Binarna številka ima lahko dve možni vrednosti 0 ali 1. Kot programerju na začetni ravni ni treba delati z operacijami na bitni ravni.

Dovolj je delo s primitivnimi podatkovnimi vrstami, kot so: celo število, float, logična vrednost, niz itd. Ko se ukvarjate s programiranjem na nizki ravni, boste morda morali delati na bitni ravni.

Swift poleg osnovnih operaterjev ponuja bogat nabor operaterjev za manipulacijo bitov. Ti operaterji so podobni logičnim operatorjem, le da delujejo na binarnih predstavitvah podatkov (bitov).

Bitni operatorji so operatorji, ki se uporabljajo za spreminjanje posameznih bitov operanda. Operand je spremenljivka ali konstanta, v kateri se izvede operacija.

Vsi bitni operatorji, ki so na voljo v hitrem načinu, so navedeni spodaj:

1. Bitno NE operater

Predstavlja ga ~znak tilde in se lahko uporablja na enem operandu. To obrne vse bite. tj. spremembe 1 na 0 in 0 na 1.

Če je x spremenljivka / konstanta, ki vsebuje binarno vrednost, tj. 0 ali 1. Bitno delovanje brez spremenljivke x lahko predstavimo v spodnji tabeli:

NE
x ~ x
0 1.
1. 0

Primer 1: Bitni operator NOT za nepodpisano celo število

 let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber) 

Ko zaženete zgornji program, bo rezultat:

 254

V zgornjem programu je stavek let initalNumber:UInt8 = 1tipa Unsigned int velikosti 8 bitov. Torej, 1 v decimalki lahko predstavimo kot 00000001v binarni obliki.

Bitni operater ne spremeni vseh bitov spremenljivke ali konstante, bit 0 se spremeni v 1 in 1 v 0. Torej invertedNumber vsebuje bitove 11111110. Po pretvorbi v decimalno vrednost je predstavljen kot 254. Torej stavek print(invertedNumber)na zaslonu prikaže 254.

Bitni operator lahko izvedete tudi neposredno v bitih kot:

2. primer: Bitni operator NOT v bitih

 let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits) 

Ko zaženete zgornji program, bo rezultat:

 0

InitialBits vsebuje binarno vrednost, 11111111ki ustreza 255 v decimalnih številkah. Za predstavitev števila v binarni obliki imamo 0bv dobesednem besedilu predpono. Brez 0bpredpone bo to obravnaval kot običajno celo število in prišlo bo do napake pri prelivanju (UInt8 lahko shrani številke od samo 0 do 255).

Ker smo uporabili bitni ne operator, spremeni vseh 1 na 0. Torej, konstanta invertedBits vsebuje, 00000000kar je enako 0 in UInt8.

Primer 3: Bitni operator NOT za podpisano celo število

 let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber) 

Ko zaženete zgornji program, bo rezultat:

 -2

V zgornjem programu je lahko 1 v decimalni obliki predstavljen kot 00000001v binarni obliki. Bitni operator ne spremeni vseh bitov spremenljivke ali konstante, bit 0 se spremeni v 1 in 1 v 0. Torej, invertedNumber vsebuje bitove 11111110. To bi moralo prikazati 254 na zaslonu. Toda namesto tega vrne -2. Čudno, kajne ?? Spodaj raziščimo, kako se je to zgodilo.

let initalNumber:Int = 1je podpisan int, ki lahko vsebuje pozitivna in negativna cela števila. Zato, ko smo uporabili operator ne za podpisano celo število, lahko vrnjeni binarni sistem predstavlja tudi negativno število.

Kako je prevajalnik interpretiral -2 kot 11111110 v binarni obliki?

Prevajalnik je za predstavitev celih števil uporabil dopolnilo Two. Če želite dobiti komplementarni negativni zapis celotnega števila, najprej zapišite številko v binarni obliki, nato obrnite števke in dodajte eno rezultatu.

Koraki za ugotovitev dopolnitve Two-a -2 :

  1. Zapiši 2 v binarni obliki: 00000010
  2. Pretvori številke. 0 postane 1 in 1 postane 0:11111101
  3. Dodaj 1: 11111110

Tako prevajalnik binarno število razlaga 1111110kot -2decimalno. Toda prevajalnik je naredil majhen preobrat, ki ga nismo opazili. Izvedel je tudi vrsto invertedNumber kot Int8tip.

Da bi to razumeli, si oglejmo spodnji primer:

 print(Int8(bitPattern: 0b11111110)) print(0b11111110)

Ko zaženete zgornji program, bo rezultat:

 -2 254

V zgornjem primeru je prevajalnik binarno število obravnaval na -2 v decimalni številki samo za podpisano 8-bitno celo število. Zato stavek print(Int8(bitPattern: 0b11111110))na zaslonu izpiše -2.

Toda za običajni celoštevilski tip, katerega velikost je 32/64 bitov in lahko vsebuje velike vrednosti, to vrednost razlaga kot 254. Zato je izjava print(0b11111110)izhodi 254 na zaslonu.

2. Bitni in operater

Predstavljata ga &in se lahko uporablja na dveh operandih. Operator AND primerja dva bita in vrne 1, če sta oba bita 1, sicer vrne 0.

Če sta x in y spremenljivka / konstanta, ki vsebuje binarno vrednost, tj. 0 ali 1. Bitno operacijo AND na x in y lahko predstavimo v spodnji tabeli:

IN
x y x & y
0 0 0
0 1. 0
1. 1. 1.
1. 0 0

Primer 5: Bitno delovanje IN

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits & yBits print("Binary:",String(result, radix: 2)) print(result)

Ko zaženete zgornji program, bo rezultat:

 Binarno: 10000011 131 

V zgornjem programu stavek let result = xBits & yBitszdružuje bita dveh operandov xBits in yBits. Vrne 1, oba bita sta 1, sicer vrne 0.

String(value , radix: )inicializator se uporablja za predstavitev števila v različnih številskih sistemih Če dobimo vrednost radix 2. Število pretvori v binarni številski sistem. Podobno lahko uporabimo 16 za šestnajstiško in 10 za decimalno.

Izjava print("Binary:",String(result, radix: 2))izhodi Binary: 10000011 na zaslonu. 10000011je enakovredno 131 v decimalni obliki, stavek print(result)v konzoli prikaže 131.

3. Bitni ALI operater

Predstavljen je kot |in se lahko uporablja na dveh operandih. Bitni operater OR primerja dva bita in ustvari rezultat 1, če je eden ali več njegovih vhodov 1, sicer 0.

Če sta x in y spremenljivka / konstanta, ki vsebuje binarno vrednost, tj.

ALI
x y x | y
0 0 0
0 1. 1.
1. 1. 1.
1. 0 1.

Primer 6: Bitna operacija ALI

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits | yBits print("Binary:", String(result, radix: 2)) print(result) 

Ko zaženete zgornji program, bo rezultat:

 Binarno: 11111111 255 

V zgornjem programu stavek let result = xBits | yBitszdružuje bita dveh konstant xBits in yBits. Vrne 1, če je kateri koli od bitov 1, sicer vrne 0.

Stavek na zaslonu print("Binary:",String(result, radix: 2))izpiše Binary: 11111111 . Ker 11111111je enaka 255v decimalni, izjava print(result)izhodi 255 na zaslonu.

4. Bitni operater XOR

Predstavljen je kot ^in se lahko uporablja na dveh operandih. Operator XOR primerja dva bita in ustvari rezultat 1, če je natančno eden od njegovih vhodov 1, sicer vrne 0.

Če sta x in y spremenljivka / konstanta, ki vsebuje binarno vrednost, tj. 0 ali 1. Operacija bitov XOR na x in y je lahko predstavljena v spodnji tabeli:

XOR
x y x y
0 0 0
0 1. 1.
1. 1. 0
1. 0 1.

Primer 7: Bitno delovanje XOR

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits yBits print("Binary:", String(result, radix: 2)) print(result) 

Ko zaženete zgornji program, bo rezultat:

 Binarno: 1111100 124 

V zgornjem programu stavek let result = xBits yBitszdružuje bita dveh konstant xBits in yBits. Vrne 1, če je natančno eden od bitov 1, sicer vrne 0.

Stavek na zaslonu print("Binary:",String(result, radix: 2))izpiše Binarno: 1111100 (enakovredno 01111100). Ker 1111100je enaka 124v decimalni, izjava print(result)izhodi 124 na zaslonu.

5. Bit-ov premik operaterja

Ti operatorji se uporabljajo za premikanje vseh bitov v številu v levo ali desno za določeno število mest in jih je mogoče uporabiti na posameznem operandu. Predstavljen je kot <<oz >>.

Obstajata dve vrsti operaterjev izmene:

Operator v levem prestavnem položaju

  • Označeno kot <<
  • Zaradi tega se bit premakne v levo, kar določa število, ki mu sledi <<.
  • Položaji bitov, ki so bili sproženi s premikom, so zapolnjeni z ničlo.
  • Če celo število premaknete za en položaj v levo, se njegova vrednost podvoji

Primer 8: Operator prestav v levo

 let someBits:UInt8 = 0b11000100 print(someBits << 1) 

Ko zaženete zgornji program, bo rezultat:

 136

V zgornjem programu smo uporabili operater leve izmene. Uporaba <<1 pomeni premik bitov za 1 v levo. Števke se za en položaj premaknejo v levo, zadnja številka na desni pa se napolni z ničlo.

Prav tako lahko vidite, da se številka, ki se premakne "s konca" z leve strani, izgubi. Ne zavija se spet z desne. Če ga premaknete za en bit v levo, iz binarne enote odstranite enoto, v desni pa dodate 0, da zapolnite pomaknjeno vrednost, preostali bit pa se premakne v levi položaj za 1.

To vrne, 10001000kar je enakovredno 136in UInt8. Zato print(someBits << 1)stavek na zaslonu prikaže 136 .

Operator premika v bitnem položaju

  • Označeno kot >>
  • Zaradi tega se bit premakne v desno s številom, ki mu sledi >>
  • Za nepodpisana števila so položaji bitov, ki so bili sproženi s premikom, nič zapolnjeni.
  • Za podpisane številke (številke, ki so lahko tudi negativne) se z znakovnim bitom zapolnijo izpraznjene položaje bitov. Z drugimi besedami, če je število pozitivno, se uporabi 0, če je število negativno, pa 1.
  • Če ga premaknete v desno za en položaj, se njegova vrednost prepolovi.

Primer 9: Operator bitnega premika v desno za celoštevilo brez predznaka

 let someBits: UInt8 = 4 print(someBits>> 1) 

Ko zaženete zgornji program, bo rezultat:

 2.

V zgornjem programu smo uporabili operator desnega premika za celo nepodpisano celo število. Uporaba >>1 pomeni premik bitov za 1 v desno. Položaji bitov, ki so bili sproščeni z operacijo premika, so na nepodpisanem celotnem številu vedno zapolnjeni z ničlo.

Ker je 4 predstavljen kot 00000100v binarni obliki. Če ga premaknete za en bit v desno, se vrne, 00000010kar je enakovredno 2in UInt8. Zato print(someBits>> 1)stavek na zaslonu izpiše 2.

Primer 10: Operator bitnega premika v desno za podpisano celo število

 let someBits:Int = -4 print(someBits>> 1) 

Ko zaženete zgornji program, bo rezultat:

 -2

V zgornjem programu smo uporabili operator desnega premika za celo nepodpisano celo število. Za razliko od pozitivnih številk se >>pri negativnih številih namesto 0 zapolni prosto mesto 1.

Ker -4je predstavljen kot 11111100v binarni obliki. Če ga premaknete za en bit v desno in v prazno mesto postavite 1, se vrne, 11111110kar je enakovredno -2za Int8tip. Zato print(someBits>> 1)stavek na zaslonu prikaže -2.

Zanimive Članki...