1. Bitwise left shift

Ang Java ay mayroon ding 3 bitwise shift operator : Kung talagang kailangan mo, maaari mong ilipat ang lahat ng mga bit ng numero ng ilang posisyon sa kaliwa o kanan.

Upang ilipat ang mga bit ng isang numero sa kaliwa, kailangan mo ang bitwise left shift operator . Ganito ang pagkakasulat:

a << b

Nasaan aang numero kung saan ang mga bit ay inililipat, at bisang numero na nagsasaad kung gaano karaming beses ilipat ang mga bit ng numero asa kaliwa. Sa panahon ng operasyong ito, ang mga low-order bit na idinagdag sa kanan ay mga zero.

Mga halimbawa:

Halimbawa Resulta
0b00000011 << 1
0b00000110
0b00000011 << 2
0b00001100
0b00000011 << 5
0b01100000
0b00000011 << 20
0b001100000000000000000000

Ang paglipat ng isang digit sa kaliwa ay may parehong epekto sa pagpaparami ng isang numero sa 2.

Gusto mo bang i-multiply ang isang numero sa 16? Ang 16 ay kapareho ng 2 4 . Kaya't inilipat mo ang numerong 4 na digit sa kaliwa


2. Bitwise shift pakanan

Ang mga bit ay maaari ding ilipat sa kanan. Upang gawin ito, gamitin ang bitwise right shift operator . Ganito ang pagkakasulat:

a >> b

Nasaan aang numero kung saan ang mga bit ay inililipat, at bang bilang ng beses upang ilipat ang mga bit ng numero asa kanan.

Mga halimbawa:

Halimbawa Resulta
0b11000011 >> 1
0b01100001
0b11000011 >> 2
0b00110000
0b11000011 >> 5
0b00000110
0b11000011 >> 20
0b00000000

Ang paglipat ng isang digit sa kanan ay may parehong epekto sa paghahati ng isang numero sa 2.

Sa panahon ng operasyong ito, ang mga high-order bit na idinagdag sa kaliwa ay mga zero, ngunit hindi palaging !

Mahalaga!

Ang pinakakaliwang bit ng isang sign na numero ay tinatawag na sign bit : kung ang numero ay positibo, ito ay 0; ngunit kung negatibo ang numero, ang bit na ito ay 1.

Kapag inililipat ang mga bit ng isang numero sa kanan, ang halaga ng sign bit ay karaniwang nagbabago din at ang sign ng numero ay mawawala. Alinsunod dito, para sa mga negatibong numero (kung saan ang pinakakaliwang bit ay 1), ang bit na ito ay nakakakuha ng espesyal na paggamot. Kapag inililipat ang mga bit ng isang numero sa kanan, 0idinaragdag ang a sa kaliwa kung ang pinakakaliwang bit ay 0, at 1idinaragdag ang a sa kaliwa kung ang pinakakaliwang bit ay 1.

Ngunit sa halimbawa sa itaas, mukhang hindi iyon ang resulta. Bakit? Dahil ang mga literal na integer ay ints, at  talagang nangangahulugang . Iyon ay, ang pinakakaliwang bit ay zero.0b111111110b00000000000000000000000011111111

Maraming programmer ang nadidismaya sa pag-uugaling ito sa right-shift at mas gugustuhin na ang numero ay laging may mga sero. Kaya nagdagdag ang Java ng isa pang right shift operator .

Ganito ang pagkakasulat:

a >>> b

Nasaan a ang numero kung saan ang mga bit ay inililipat, at b  ang bilang ng beses upang ilipat ang mga bit ng numero asa kanan. Ang operator na ito ay palaging nagdaragdag ng mga zero sa kaliwa, anuman ang orihinal na halaga ng sign bit ng numero a.



3. Paggawa gamit ang mga flag

Lumikha ang mga programmer ng halos ganap na bagong larangan ng pag-aaral batay sa bitwise at shift operations: nagtatrabaho sa mga flag.

Kapag ang mga computer ay may napakakaunting memorya, napakapopular na mag-cram ng maraming impormasyon sa iisang numero. Ang isang numero ay itinuring bilang isang array ng mga bit: ang isang int ay 32 bits, at ang isang mahaba ay 64 bits.

Maaari kang magsulat ng maraming impormasyon sa naturang numero, lalo na kung kailangan mong mag-imbak ng mga lohikal ( trueo false) na halaga. Ang single longay parang booleanarray na binubuo ng 64 na elemento. Ang mga bit na ito ay tinatawag na mga flag at manipulahin gamit ang mga sumusunod na operasyon:

  • itakda ang bandila
    (gumawa ng isang tiyak na bit na katumbas ng 1)
  • i-reset ang bandila
    (gumawa ng isang tiyak na bit na katumbas ng 0)
  • suriin ang bandila
    (suriin ang halaga ng isang partikular na bit)

At narito kung paano ito ginagawa sa mga bitwise operator.

Pagtatakda ng bandila

Upang magtakda ng isang partikular na bit sa 1, kailangan mong magsagawa ng bitwise OR na operasyon sa pagitan ng numero na nais mong itakda ang bit at isang espesyal na nilikhang numero, kung saan ang bit na iyon lamang ang 1.

Halimbawa, ipagpalagay na mayroon kang numero 0b00001010at kailangan mong itakda ang 5th bit sa 1. Sa kasong iyon, kailangan mong:

0b00001010 | 0b00010000 = 0b00011010

Kung ang 5th bit ay naitakda na sa isa, kung gayon walang magbabago.

Sa pangkalahatan, ang pagpapatakbo ng pagtatakda ng bandila ay maaaring isulat bilang mga sumusunod

a | (1 << b)

Nasaan a ang numero kung saan ang bit ay itatakda sa 1. At b ang posisyon ng bit na itatakda. Ang paggamit ng left shift operator ay sobrang maginhawa rito, dahil masasabi mo kaagad kung aling bit ang pinagtatrabahuhan namin.

Pag-reset ng bandila

Upang i-reset ang isang partikular na bit (ibig sabihin, itakda ito sa 0) ​​nang hindi nakakagambala sa iba pang mga bit, kailangan mong magsagawa ng &operasyon sa pagitan ng numero kung saan ang bit na gusto mong i-reset (ibig sabihin, nakatakda sa 0) ​​at isang espesyal na nilikhang numero, kung saan ang lahat ng mga bit ay katumbas ng 1maliban para sa bit na gusto mong i-reset.

Halimbawa, ipagpalagay na mayroon kang numero 0b00001010at kailangan mong itakda ang 4th bit sa 0. Sa kasong iyon, kailangan mong:

0b00001010 & 0b11110111 = 0b00000010

Kung ang 4th bit ay naitakda na sa zero, kung gayon walang magbabago.

Sa pangkalahatan, ang pagpapatakbo ng pag-reset ng bandila ay maaaring isulat bilang mga sumusunod

a & ~(1 << b)

Nasaan a ang numero kung saan ang bit ay ire-reset sa 0. At b ang posisyon ng bit ay i-clear.

Upang makakuha ng isang numero kung saan ang lahat ng mga bit ay 1maliban sa isa na gusto nating maging zero, inilipat muna natin ang 1 b  na posisyon sa kaliwa, at pagkatapos ay gamitin ang bitwise NOToperator upang baligtarin ang resulta.

Sinusuri ang isang bandila

Bilang karagdagan sa pagtatakda o pag-reset ng isang partikular na flag, minsan kailangan mo lang suriin kung ang isang ibinigay na flag ay nakatakda, ibig sabihin, kung ang isang partikular na bit ay katumbas ng 1. Ito ay medyo madaling gawin sa isang bitwise &.

Halimbawa, ipagpalagay na kailangan mong suriin kung ang 4th bit ay nakatakda 1sa numero 0b00001010. Pagkatapos ay kailangan mong gawin ito:

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

Sa pangkalahatan, ang operasyon ng pagsuri sa isang bandila ay maaaring isulat bilang mga sumusunod

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

Nasaan a ang numero na ang bit ay sinusuri. At b ang posisyon ng bit na susuriin.


4. Pag-encrypt

Ang bitwise XORna operasyon ay kadalasang ginagamit ng mga programmer para sa simpleng pag-encrypt. Sa pangkalahatan, ganito ang hitsura ng naturang pag-encrypt:

result = number ^ password;

Nasaan number ang data na gusto naming i-encrypt, password ay isang espesyal na numero na ginagamit bilang isang "password" para sa data, at result ang naka-encrypt na numero.

number == (number ^ password) ^ password;

Ang mahalagang bagay dito ay kapag ang XORoperator ay inilapat sa isang numero ng dalawang beses, ito ay gumagawa ng orihinal na numero, anuman ang "password".

Upang mabawi number mula sa encrypted result, kailangan mo lamang gawin muli ang operasyon:

original number = result ^ password;

Halimbawa:

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