Các toán tử Bitwise
1. Bitwise
Trong lập trình máy tính kỹ thuật số. Phép toán bitwise hoạt động trên một hoặc nhiều số nhị phân (binary numerals), hoặc các chuỗi giống số nhị phân. Đây là một phép toán đơn giản và nhanh, được hỗ trợ trực tiếp bởi bộ xử lý (processor). Thông thường các phép tính bitwise nhanh hơn rất nhiều so với phép nhân, phép chia, đôi khi nhanh hơn đáng kể so với phép cộng. Các phép tính bitwise sử dụng ít năng lượng hơn bởi nó ít sử dụng tài nguyên.
Có 7 phép toán bitwise:
Operator | Name | Description |
& | AND | Nếu cả 2 bit là 1, giá trị trả về là 1, ngược lại trả về 0. |
| | OR | Nếu một trong hai bit là 1, giá trị trả về là 1, ngược lại trả về 0. |
^ | XOR | Nếu hai bit khác nhau, giá trị trả về là 1, ngược lại trả về 0. |
~ | NOT | Đảo ngược tất cả các bit, 0 thành 1 và 1 thành 0. |
<< | Zero fill left shift | Dịch chuyển tất cả các bit sang bên trái. |
>> | Signed right shift | Dịch chuyển tất cả các bit sang bên phải ngoại trừ bit đầu tiên. |
>>> | Zero fill right shift | Dịch chuyển tất cả các bit sang bên phải. |
Bitwise AND
Khi một bitwise AND được thực hiện trên một cặp bit, nó trả về 1 nếu cả 2 bit là 1, ngược lại trả về 0.
Ví dụ với 1 bit:
Operation | Result |
0 & 0 | 0 |
0 & 1 | 0 |
1 & 0 | 0 |
1 & 1 | 1 |
Ví dụ với 4 bit:
Operation | Result |
1111 & 0000 | 0000 |
1111 & 0001 | 0001 |
1111 & 0010 | 0010 |
1111 & 0100 | 0100 |
Bitwise OR:
Khi một bitwise OR được thực hiện trên một cặp bit, nó trả về 1 nếu một trong các bit là 1, ngược lại trả về 0.
Ví dụ với 1 bit:
Operation | Result |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Ví dụ với 4 bit:
Operation | Result |
1111 | 0000 | 1111 |
1111 | 0001 | 1111 |
1111 | 0010 | 1111 |
1111 | 0100 | 1111 |
Bitwise XOR
Khi một bitwise XOR được thực hiện trên một cặp bit, nó trả về 1 nếu các bit khác nhau, ngược lại trả về 0.
Ví dụ với 1 bit:
Operation | Result |
0 ^ 0 | 0 |
0 ^ 1 | 1 |
1 ^ 0 | 1 |
1 ^ 1 | 0 |
Ví dụ với 4 bit:
Operation | Result |
1111 ^ 0000 | 1111 |
1111 ^ 0001 | 1110 |
1111 ^ 0010 | 1101 |
1111 ^ 0100 | 1011 |
Bitwise NOT
Khi một Bitwise NOT được sử dụng nó sẽ đảo ngược tất cả các bit. 1 thành 0, và 0 thành 1.
Ví dụ với 1 bit:
Operation | Result |
~ 0 | 1 |
~ 1 | 0 |
Ví dụ với 4 bit:
Operation | Result |
~ 0000 | 1111 |
~ 0001 | 0001 |
~ 0010 | 1101 |
~ 1100 | 0011 |
2. Phép toán Bitwise trên các số
Các ngôn ngữ khác nhau có thể có nhiều kiểu dữ liệu để biểu diễn số.
- Java: byte, short, int, long, double.
- C#:byte, sbyte, short, ushort, int, uint, long, ulong, float, double
- Javascript: double
- .....
Javascript lưu trữ các số như là các số chấm động 64 bit (64 bits floating point numbers). Nhưng các phép toán bitwise được thực hiện trên các số nguyên 32 bit. Các ngôn ngữ khác như Java, C#,.. các phép toán bitwise cũng được thực hiện trên các số nguyên 32 bit.
Vì vậy trước khi thực hiện phép toán bitwise với các số bạn phải chuyển đổi mỗi số thành một dẫy 32 số nhị phân.
Base 10 | Base 2 | 32 bits |
5 | 101 | 00000000000000000000000000000101 |
218 | 11011010 | 00000000000000000000000011011010 |
Trong Javascript phương thức toString(base) giúp bạn chuyển một số bất kỳ từ hệ cơ số 10 (base 10) sang hệ cơ số khác.
toString-base-example.js (Javascript)
let a = 8;
// Base 2 string.
console.log( a.toString(2) );// 1000
// Base 8 string
console.log( a.toString(8) ); // 10
// Base 16 string
console.log( a.toString(16) ); // 8
let b = 218;
// Base 2 string.
console.log( b.toString(2) );// 11011010
// Base 8 string
console.log( b.toString(8) ); // 332
// Base 16 string
console.log( b.toString(16) ); // da
Ví dụ:
Decimal | Binary |
5 | 00000000000000000000000000000101 |
1 | 00000000000000000000000000000001 |
5 & 1 = 1 | 00000000000000000000000000000001 |
5 | 1 = 5 | 00000000000000000000000000000101 |
5 ^ 1 = 4 | 00000000000000000000000000000100 |
~ 5 = -6 | 11111111111111111111111111111010 |
Chú ý: Trong 32 bit, bit đầu tiên được sử dụng để xác định dấu (sign) của số, nếu bit này là 1 tương ứng với dấu trừ ( - ), nếu bit này là 0 tương ứng với dấu cộng ( + )
Bitwise Left Shift (<<)
Decimal | Binary |
5 | 00000000000000000000000000000101 |
5 << 1 = 10 | 00000000000000000000000000001010 |
5 << 2 = 20 | 00000000000000000000000000010100 |
Toán tử Bitwise Left Shift ( << ) có thể làm thay đổi dấu (sign) của số.
(Javascript code)
console.log( 1073741824 << 1); // -2147483648
console.log( 2684354560 << 1); // 1073741824
Bitwise Right Shift (>>) [Unsigned Right Shift]
Decimal | Binary |
29 | 00000000000000000000000000011101 |
29 >> 1 = 14 | 00000000000000000000000000001110 |
29 >> 2 = 7 | 00000000000000000000000000000111 |
Toán tử Bitwise Right Shift ( >> ) không làm thay đổi dấu của số, vì bit đầu tiên không bị di chuyển.
Bitwise Right Shift (>>>) [Zero fill right Shift]
Toán tử Bitwise Right Shift ( >>> ) có thể làm thay đổi dấu của số.
(Javascript Code)
console.log( -1073741824 >>> 1); // 1610612736
console.log( 1073741824 >>> 1); // 536870912
3. Bitwise để làm gì?
Các phép tính bitwise được hỗ trợ trực tiếp bởi bộ xử lý (processor) của máy tính nên nó thực hiện rất nhanh. Dưới đây tôi liệt kê một vài ví dụ sử dụng các phép toán này.
Sử dụng các phép toán bitwise trên các String (characters) trên các ngôn ngữ Java, C#, C/C++ ... Chú ý: một vài ngôn ngữ như Javascript không hỗ trợ phép toán bitwise với kiểu String.
Chuyển đổi một chữ hoa (Uppercase) sang chữ thường (Lowercase):
// Rule: x | ' '
('A' | ' ') ==> 'a'
('B' | ' ') ==> 'b'
('a' | ' ') => 'a'
Chuyển đổi chữ thường (Lowercase) sang chữ hoa (Uppercase):
// Rule: x & '_'
('a' & '_') ==> 'A'
('b' & '_') ==> 'B'
('A' & '_') ==> 'A'
Đảo ngược chữ hoa thành chữ thường, chữ thường thành chữ hoa:
// Rule: x ^ ' '
('a' ^ ' ') ==> 'A'
('A' ^ ' ') ==> 'a'
Xem vị trí các chữ cái Latin (Chỉ áp dụng cho chữ hoa)
// Rule: x & '?'
'A' & '?' ==> 1
'B' & '?' ==> 2
...
'Z' & '?' ==> 26
// Rule: x ^ '@'
'A' ^ '@' ==> 1
'B' ^ '@' ==> 2
...
'Z' ^ '@' ==> 26
Xem vị trí các chữ cái Latin (Chỉ áp dụng cho chữ thường)
// Rule: x ^ '`'
'a' ^ '`' ==> 1
'b' ^ '`' ==> 2
...
'z' ^ '`' ==> 26
// '`' : binary ( 1100000 ), hex('60'), chr(96)
Xem vị trí các chữ cái Latin, áp dụng cho cả chữ hoa và chữ thường:
// Rule: x & '\u001F'
'A' & '\u001F' ==> 1
'B' & '\u001F' ==> 2
...
'Z' & '\u001F' ==> 26
'A' & '\u001F' ==> 1
'B' & '\u001F' ==> 2
...
'Z' & '\u001F' ==> 26
Các hướng dẫn ECMAScript, Javascript
- Giới thiệu về Javascript và ECMAScript
- Bắt đầu nhanh với Javascript
- Hộp thoại Alert, Confirm, Prompt trong Javascript
- Bắt đầu nhanh với JavaScript
- Biến (Variable) trong JavaScript
- Các toán tử Bitwise
- Mảng (Array) trong JavaScript
- Vòng lặp trong JavaScript
- Hàm trong JavaScript
- Hướng dẫn và ví dụ JavaScript Number
- Hướng dẫn và ví dụ JavaScript Boolean
- Hướng dẫn và ví dụ JavaScript String
- Câu lệnh rẽ nhánh if/else trong JavaScript
- Câu lệnh rẽ nhánh switch trong JavaScript
- Hướng dẫn xử lý lỗi trong JavaScript
- Hướng dẫn và ví dụ JavaScript Date
- Hướng dẫn và ví dụ JavaScript Module
- Lịch sử phát triển của module trong JavaScript
- Hàm setTimeout và setInterval trong JavaScript
- Hướng dẫn và ví dụ Javascript Form Validation
- Hướng dẫn và ví dụ JavaScript Web Cookie
- Từ khóa void trong JavaScript
- Lớp và đối tượng trong JavaScript
- Kỹ thuật mô phỏng lớp và kế thừa trong JavaScript
- Thừa kế và đa hình trong JavaScript
- Tìm hiểu về Duck Typing trong JavaScript
- Hướng dẫn và ví dụ JavaScript Symbol
- Hướng dẫn JavaScript Set Collection
- Hướng dẫn JavaScript Map Collection
- Tìm hiểu về JavaScript Iterable và Iterator
- Hướng dẫn sử dụng biểu thức chính quy trong JavaScript
- Hướng dẫn và ví dụ JavaScript Promise, Async Await
- Hướng dẫn và ví dụ Javascript Window
- Hướng dẫn và ví dụ Javascript Console
- Hướng dẫn và ví dụ Javascript Screen
- Hướng dẫn và ví dụ Javascript Navigator
- Hướng dẫn và ví dụ Javascript Geolocation API
- Hướng dẫn và ví dụ Javascript Location
- Hướng dẫn và ví dụ Javascript History API
- Hướng dẫn và ví dụ Javascript Statusbar
- Hướng dẫn và ví dụ Javascript Locationbar
- Hướng dẫn và ví dụ Javascript Scrollbars
- Hướng dẫn và ví dụ Javascript Menubar
- Hướng dẫn xử lý JSON trong JavaScript
- Xử lý sự kiện (Event) trong Javascript
- Hướng dẫn và ví dụ Javascript MouseEvent
- Hướng dẫn và ví dụ Javascript WheelEvent
- Hướng dẫn và ví dụ Javascript KeyboardEvent
- Hướng dẫn và ví dụ Javascript FocusEvent
- Hướng dẫn và ví dụ Javascript InputEvent
- Hướng dẫn và ví dụ Javascript ChangeEvent
- Hướng dẫn và ví dụ Javascript DragEvent
- Hướng dẫn và ví dụ Javascript HashChangeEvent
- Hướng dẫn và ví dụ Javascript URL Encoding
- Hướng dẫn và ví dụ Javascript FileReader
- Hướng dẫn và ví dụ Javascript XMLHttpRequest
- Hướng dẫn và ví dụ Javascript Fetch API
- Phân tích XML trong Javascript với DOMParser
- Giới thiệu về Javascript HTML5 Canvas API
- Làm nổi bật Code với thư viện Javascript SyntaxHighlighter
- Polyfill là gì trong khoa học lập trình?
Show More
Java cơ bản
- Tùy biến trình biên dịch java xử lý Annotation của bạn (Annotation Processing Tool)
- Lập trình Java theo nhóm sử dụng Eclipse và SVN
- Hướng dẫn và ví dụ Java WeakReference
- Hướng dẫn và ví dụ Java PhantomReference
- Hướng dẫn nén và giải nén trong Java
- Cấu hình Eclipse để sử dụng JDK thay vì JRE
- Phương thức String.format() và printf() trong Java
- Cú pháp và các tính năng mới trong Java 5
- Cú pháp và các tính năng mới trong Java 8
- Hướng dẫn sử dụng biểu thức chính quy trong Java
- Hướng dẫn lập trình đa luồng trong Java - Java Multithreading
- Thư viện điều khiển các loại cơ sở dữ liệu khác nhau trong Java
- Hướng dẫn sử dụng Java JDBC kết nối cơ sở dữ liệu
- Lấy các giá trị của các cột tự động tăng khi Insert một bản ghi sử dụng JDBC
- Hướng dẫn và ví dụ Java Stream
- Functional Interface trong Java
- Giới thiệu về Raspberry Pi
- Hướng dẫn và ví dụ Java Predicate
- Abstract class và Interface trong Java
- Access modifier trong Java
- Hướng dẫn và ví dụ Java Enum
- Hướng dẫn và ví dụ Java Annotation
- So sánh và sắp xếp trong Java
- Hướng dẫn và ví dụ Java String, StringBuffer và StringBuilder
- Hướng dẫn xử lý ngoại lệ trong Java - Java Exception Handling
- Hướng dẫn và ví dụ Java Generics
- Thao tác với tập tin và thư mục trong Java
- Hướng dẫn và ví dụ Java BiPredicate
- Hướng dẫn và ví dụ Java Consumer
- Hướng dẫn và ví dụ Java BiConsumer
- Bắt đầu với Java cần những gì?
- Lịch sử của Java và sự khác biệt giữa Oracle JDK và OpenJDK
- Cài đặt Java trên Windows
- Cài đặt Java trên Ubuntu
- Cài đặt OpenJDK trên Ubuntu
- Cài đặt Eclipse
- Cài đặt Eclipse trên Ubuntu
- Học nhanh Java cho người mới bắt đầu
- Lịch sử của bit và byte trong khoa học máy tính
- Các kiểu dữ liệu trong Java
- Các toán tử Bitwise
- Câu lệnh rẽ nhánh (if else) trong Java
- Câu lệnh rẽ nhánh switch trong Java
- Vòng lặp trong Java
- Mảng (Array) trong Java
- JDK Javadoc định dạng CHM
- Thừa kế và đa hình trong Java
- Hướng dẫn và ví dụ Java Function
- Hướng dẫn và ví dụ Java BiFunction
- Ví dụ về Java encoding và decoding sử dụng Apache Base64
- Hướng dẫn và ví dụ Java Reflection
- Hướng dẫn gọi phương thức từ xa với Java RMI
- Hướng dẫn lập trình Java Socket
- Các nền tảng nào bạn nên chọn để lập trình ứng dụng Java Desktop?
- Hướng dẫn và ví dụ Java Commons IO
- Hướng dẫn và ví dụ Java Commons Email
- Hướng dẫn và ví dụ Java Commons Logging
- Tìm hiểu về Java System.identityHashCode, Object.hashCode và Object.equals
- Hướng dẫn và ví dụ Java SoftReference
- Hướng dẫn và ví dụ Java Supplier
- Lập trình Java hướng khía cạnh với AspectJ (AOP)
Show More
- Hướng dẫn lập trình Java Servlet/JSP
- Các hướng dẫn Java Collections Framework
- Java API cho HTML & XML
- Các hướng dẫn Java IO
- Các hướng dẫn Java Date Time
- Các hướng dẫn Spring Boot
- Các hướng dẫn Maven
- Các hướng dẫn Gradle
- Các hướng dẫn Java Web Services
- Các hướng dẫn lập trình Java SWT
- Các hướng dẫn lập trình JavaFX
- Các hướng dẫn Java Oracle ADF
- Các hướng dẫn Struts2 Framework
- Các hướng dẫn Spring Cloud