CodeGym /Blog Java /Ngẫu nhiên /Toán tử Java Bitwise

Toán tử Java Bitwise

Xuất bản trong nhóm
Trong bài học hôm nay, chúng ta sẽ làm quen với Java Bitwise Operator và xem xét các ví dụ về cách làm việc với chúng. Có lẽ bạn đã quen thuộc với từ "bit". Nếu không, hãy nhớ lại ý nghĩa của nó :) Bit là đơn vị thông tin nhỏ nhất trong máy tính. Tên của nó xuất phát từ chữ số nhị phân . Một bit có thể được biểu thị bằng một trong hai số: 1 hoặc 0. Có một hệ thống số nhị phân đặc biệt dựa trên số 1 và số 0. Chúng ta sẽ không đào sâu vào một khu rừng toán học ở đây. Chúng tôi sẽ chỉ lưu ý rằng bất kỳ số nào trong Java đều có thể được chuyển đổi thành dạng nhị phân. Để làm điều này, bạn cần sử dụng các lớp bao bọc.
Toán tử bitwise - 1
Ví dụ, đây là cách bạn có thể làm điều này cho một int :

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Đầu ra của bàn điều khiển: 101010110 1010 10110 (tôi đã thêm khoảng trắng để dễ đọc hơn) là số 342 trong hệ thập phân. Chúng tôi thực sự đã chia nhỏ con số này thành các bit riêng lẻ: số không và số một. Các hoạt động được thực hiện trên các bit được gọi là bitwise .
  • ~ - bit KHÔNG.
Toán tử này rất đơn giản: nó chuyển qua từng bit của số của chúng ta và đảo bit: số 0 trở thành số 1 và số 1 trở thành số không. Nếu chúng ta áp dụng nó cho số 342 của mình, đây là điều sẽ xảy ra: 101010110 là 342 được biểu thị dưới dạng số nhị phân 010101001 là giá trị của biểu thức ~342 Hãy thử áp dụng điều này vào thực tế:

public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(~x);
   }
}
Đầu ra của bảng điều khiển: 169 169 là kết quả của chúng tôi ( 010101001 ) trong hệ thập phân quen thuộc :)
  • & - theo bit AND
Như bạn có thể thấy, nó trông khá giống với logic AND ( && ). Toán tử && , bạn sẽ nhớ lại, chỉ trả về giá trị đúng nếu cả hai toán hạng đều đúng. Bitwise & hoạt động theo cách tương tự: nó so sánh hai số từng chút một. Việc so sánh tạo ra một số thứ ba. Ví dụ: hãy lấy các số 277 và 432: 110110000 là 277 được biểu diễn dưới dạng số nhị phân 1000101011 là 432 được biểu diễn dưới dạng số nhị phân Tiếp theo, toán tử & so sánh bit đầu tiên của số trên với bit đầu tiên của số dưới cùng. Vì đây là toán tử AND nên kết quả sẽ là 1 chỉ khi cả hai bit đều là 1. Trong bất kỳ trường hợp nào khác, kết quả là 0. 100010101 &Toán tử & Đầu tiên, chúng ta so sánh các bit đầu tiên của hai số, sau đó là các bit thứ hai, rồi đến bit thứ ba, v.v. Như bạn có thể thấy, chỉ trong hai trường hợp cả hai bit tương ứng đều có số bằng 1 (bit thứ nhất và bit thứ năm). Tất cả các so sánh khác tạo ra 0s. Vì vậy, cuối cùng chúng ta có số 10001000. Trong hệ thập phân, nó tương ứng với số 272. Hãy kiểm tra:

public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Đầu ra bảng điều khiển: 272
  • | - từng bit HOẶC.
Toán tử này hoạt động theo cùng một cách: so sánh hai số từng chút một. Chỉ bây giờ nếu ít nhất một trong các bit là 1, thì kết quả là 1. Hãy xem xét các số giống nhau (277 và 432): 100010101 | 110110000 _______________ 110110101 - kết quả của | Toán tử Đây là kết quả khác: các bit duy nhất còn lại số không là những bit đã từng là số không trong cả hai số. Kết quả là số 110110101. Trong hệ thập phân, nó tương ứng với số 437 Hãy kiểm tra:

public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Đầu ra bảng điều khiển: 437 Chúng tôi đã tính toán mọi thứ chính xác! :)
  • ^ - bitwise XOR (độc quyền HOẶC)
Chúng tôi chưa gặp toán tử này. Nhưng không có gì phức tạp về nó. Nó tương tự như toán tử OR thông thường. Có một điểm khác biệt: OR thông thường trả về true nếu ít nhất một toán hạng là true. Nhưng nó không nhất thiết phải là một: nếu cả hai toán hạng đều đúng, thì kết quả là đúng. Nhưng OR độc quyền chỉ trả về true nếu chính xác một trong các toán hạng là true. Nếu cả hai toán hạng đều đúng, phép toán OR thông thường trả về giá trị đúng ("ít nhất một giá trị đúng"), nhưng XOR trả về giá trị sai. Đó là lý do tại sao nó được gọi là OR độc quyền. Biết cách hoạt động của các toán tử bitwise trước đó, bạn có thể dễ dàng tính được 277 ^ 432. Nhưng chúng ta hãy cùng nhau tìm hiểu kỹ hơn một lần nữa :) 100010101 ^ 110110000 _______________ 010100101 - kết quả của phép toán ^nhà điều hành Đó là kết quả của chúng tôi. Những bit giống nhau trong cả hai số tạo ra 0 (có nghĩa là thử nghiệm "chỉ một" không thành công). Nhưng các bit tạo thành cặp 0-1 hoặc 1-0 đã trở thành cặp. Kết quả của chúng tôi là số 010100101. Trong hệ thập phân, nó tương ứng với số 165. Hãy xem tính toán của chúng tôi có đúng không:

public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Đầu ra bảng điều khiển: 165 Siêu! Mọi thứ đúng như chúng ta nghĩ :) Bây giờ là lúc làm quen với các toán tử dịch chuyển bit. Tên nói cho chính nó. Chúng tôi lấy một số và di chuyển các bit của nó sang trái hoặc phải :) Hãy xem nó trông như thế nào:

Sang trái

Việc dịch chuyển các bit sang trái được biểu thị bằng << Đây là một ví dụ:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
Trong ví dụ này, số x = 64 được gọi là giá trị. Đó là các bit của giá trị mà chúng tôi sẽ thay đổi. Chúng ta sẽ dịch chuyển các bit sang trái (bạn có thể đoán điều này theo hướng của toán tử << ) Trong hệ thống nhị phân, số 64 = 1000000 Số y = 3 được gọi là khoảng cách dịch chuyển. Khoảng cách dịch chuyển cho biết bạn muốn dịch chuyển các bit của số x sang phải/trái bao nhiêu bit . Trong ví dụ của chúng tôi, chúng tôi sẽ dịch chuyển chúng sang trái 3 bit. Để thấy quá trình chuyển đổi rõ ràng hơn, hãy nhìn vào hình ảnh. Trong ví dụ này, chúng tôi sử dụng int s. Số nguyên chiếm 32 bit trong bộ nhớ của máy tính. Đây là số 64 ban đầu của chúng tôi trông như thế nào:
Toán tử bitwise - 2
Và bây giờ chúng tôi lấy từng bit của mình và dịch chuyển chúng sang trái 3 vị trí theo đúng nghĩa đen:
Toán tử bitwise - 3
Hãy nhìn vào những gì chúng tôi có. Như bạn có thể thấy, tất cả các bit của chúng tôi đã thay đổi và 3 số không khác đã được thêm vào từ cạnh của phạm vi. Ba, bởi vì chúng tôi đã dịch chuyển 3. Nếu chúng tôi đã dịch chuyển 10, thì 10 số 0 sẽ được thêm vào. Do đó, biểu thức x << y có nghĩa là "chuyển các bit của số x sang trái theo y vị trí". Kết quả của biểu thức của chúng ta là số 1000000000, là 512 trong hệ thập phân. Hãy kiểm tra:

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 3;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Đầu ra bảng điều khiển: 512 Bật ngay! Về mặt lý thuyết, các bit có thể được dịch chuyển vô tận, nhưng vì số của chúng tôi là một int nên chúng tôi chỉ có sẵn 32 chữ số nhị phân. Trong số này, 7 đã được chiếm bởi 64 (1000000). Do đó, nếu chúng ta dịch chuyển 27 vị trí sang trái, thì vị trí duy nhất của chúng ta sẽ vượt ra ngoài phạm vi của loại dữ liệu và bị mất. Chỉ số không sẽ còn lại!

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 26;// Shift distance

       int z = (x << y);
       System.out.println(z);
   }
}
Đầu ra của bàn điều khiển: 0 Như mong đợi, cái đã vượt quá 32 bit có sẵn và biến mất. Chúng tôi đã kết thúc với một số 32 bit chỉ bao gồm các số không.
Toán tử bitwise - 4
Đương nhiên, điều này tương ứng với 0 trong hệ thống thập phân. Đây là một quy tắc đơn giản để ghi nhớ các phép dịch chuyển sang trái: Đối với mỗi phép dịch chuyển sang trái, số đó được nhân với 2. Hãy thử tính biểu thức sau mà không có hình ảnh của các bit 111111111 << 3 Chúng ta cần nhân số 111111111 với 2. Kết quả là, chúng tôi nhận được 888888888. Hãy viết một số mã và kiểm tra:

public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
Đầu ra bảng điều khiển: 888888888

Dịch chuyển sang phải

Thao tác này được ký hiệu là >> . Nó làm điều tương tự, nhưng theo một hướng khác! :) Chúng tôi sẽ không phát minh lại bánh xe. Hãy thử với int 64 tương tự.

public class Main {

   public static void main(String[] args) {
       int x = 64;//value
       int y = 2;// Shift distance

       int z = (x >> y);
       System.out.println(z);
   }
}
Toán tử bitwise - 5
Toán tử bitwise - 6
Do dịch chuyển sang phải 2, hai số 0 cực trị trong số của chúng tôi di chuyển ra khỏi phạm vi và bị mất. Chúng tôi nhận được 10000, tương ứng với số 16 trong hệ thống thập phân Đầu ra của bảng điều khiển: 16 Đây là một quy tắc đơn giản để ghi nhớ các lần dịch chuyển sang phải: Mỗi lần dịch chuyển sang phải chia cho hai, loại bỏ bất kỳ phần còn lại nào. Ví dụ: 35 >> 2 có nghĩa là chúng ta cần chia 35 cho 2 hai lần, loại bỏ phần dư 35/2 = 17 (bỏ phần dư 1) 17/2 = 8 (bỏ phần dư 1) Cuối cùng, 35 >> 2 nên bằng 8. Hãy kiểm tra:

public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
Đầu ra bảng điều khiển: 8

Toán tử ưu tiên trong Java

Trong khi viết và đọc mã, bạn sẽ thường thấy các biểu thức kết hợp nhiều thao tác. Điều rất quan trọng là phải hiểu thứ tự chúng sẽ được thực hiện (nếu không, bạn có thể ngạc nhiên với kết quả) Vì Java có rất nhiều thao tác, mỗi thao tác đã được chỉ định một vị trí trong một bảng đặc biệt:

ưu tiên điều hành

nhà điều hành Quyền ưu tiên
hậu tố expr++ expr--
đơn nguyên ++expr --expr +expr ~ !
phép nhân * / %
phụ gia + -
sự thay đổi << >>>> _
quan hệ < > <= >= instanceof
bình đẳng == !=
theo bit VÀ &
bit độc quyền HOẶC ^
bao gồm từng bit HOẶC |
logic VÀ &&
logic HOẶC ||
chim nhạn ? :
phân công = += -= *= /= %= &= ^= |= <<= >>= >>>=
Tất cả các hoạt động được thực hiện từ trái sang phải, có tính đến mức độ ưu tiên của chúng. Ví dụ, nếu chúng ta viết

int x  = 6 - 4/2;
thì phép chia ( 4/2 ) sẽ được thực hiện trước. Mặc dù đứng thứ hai nhưng nó có quyền ưu tiên cao hơn. Dấu ngoặc đơn và dấu ngoặc đơn cho biết mức độ ưu tiên tối đa. Bạn có thể nhớ điều đó từ trường học. Ví dụ: nếu bạn thêm chúng vào biểu thức

int x  = (6 - 4)/2;
thì phép trừ được thực hiện trước, vì nó được đặt trong dấu ngoặc đơn. Mức độ ưu tiên của toán tử logic && khá thấp (xem bảng), do đó, nó thường sẽ ở cuối cùng. Ví dụ:

boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
Biểu thức này sẽ được thực hiện như sau:
  • 4/2 = 2

boolean x = 6 - 2 > 3 && 12*12 <= 119;
  • 12*12 = 144

boolean x = 6 - 2 > 3 && 144 <= 119;
  • 6-2 = 4

boolean x = 4 > 3 && 144 <= 119;
Tiếp theo, các toán tử so sánh được thực thi:
  • 4 > 3 = đúng

boolean x = true && 144 <= 119;
  • 144 <= 119 = sai

boolean x = true && false;
Và cuối cùng, toán tử AND ( && ) sẽ được thực hiện sau cùng.

boolean x = true && false;
boolean x = false;
Ví dụ: toán tử cộng( + ) có độ ưu tiên cao hơn toán tử so sánh != (không bằng); Vì vậy, trong biểu thức

boolean x = 7 != 6+1;
thao tác 6+1 sẽ được thực hiện trước, sau đó là kiểm tra 7 != 7 (được đánh giá là sai) và cuối cùng là gán kết quả (sai) cho biến x (gán thường có quyền ưu tiên thấp nhất trong tất cả các toán tử; xem cái bàn). Phù! Đó là một bài học lớn, nhưng bạn đã làm được! Nếu bạn không hoàn toàn hiểu một số bài học này hoặc các bài học trước, đừng lo lắng. Chúng tôi sẽ đề cập đến những chủ đề này nhiều lần trong tương lai. Một vài bài học CodeGym về các phép tính logic và số. Chúng tôi sẽ không nói đến những điều này sớm, nhưng không có hại gì nếu bạn đọc chúng bây giờ.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION