Di balik setiap angka yang kita proses tersimpan deretan bit biner 0 dan 1. Operator bitwise memungkinkan kita mengolah deretan tersebut secara langsung: menyalakan satu bit tanpa menyentuh bit lain, menggabungkan beberapa nilai kecil menjadi satu angka, atau memeriksa izin seperti read/write/execute pada sistem berkas. Pada Chapter ini kita akan membedah keenam operator bitwise beserta penerapan praktisnya.
Membaca Representasi Biner #
Fungsi bawaan bin() menampilkan bentuk biner sebuah bilangan bulat, sedangkan int() dengan basis 2 mengubah kembali string biner menjadi angka desimal:
>>> bin(12)
'0b1100'
>>> bin(10)
'0b1010'
>>> int("1100", 2)
12Prefiks 0b menandai bahwa string tersebut adalah bilangan biner. Nilai 12 tersusun dari bit 1100 (8 + 4), dan 10 tersusun dari 1010 (8 + 2). Dua bilangan ini akan kita pakai sebagai contoh sepanjang Chapter.
Enam Operator Bitwise #
| Operator | Nama | Contoh | Hasil |
|---|---|---|---|
& | AND | 12 & 10 | 8 |
| | OR | 12 | 10 | 14 |
^ | XOR | 12 ^ 10 | 6 |
~ | NOT | ~12 | -13 |
<< | Left shift | 12 << 2 | 48 |
>> | Right shift | 12 >> 2 | 3 |
Berikut hasil eksekusi seluruh operasi pada tabel di atas:
>>> 12 & 10
8
>>> 12 | 10
14
>>> 12 ^ 10
6
>>> ~12
-13
>>> 12 << 2
48
>>> 12 >> 2
3
>>> ~0
-1
>>> ~-1
0Operator &, |, dan ^ membandingkan dua bit pada posisi yang sama, kolom per kolah:
1 1 0 0 (12)
& 1 0 1 0 (10)
─────────
1 0 0 0 (8)Pada operasi &, sebuah bit hasil bernilai 1 hanya jika kedua bit sumber bernilai 1. Pada |, bit hasil bernilai 1 jika minimal salah satu bit sumber bernilai 1 (hasil 14 = 1110). Pada ^ (exclusive OR), bit hasil bernilai 1 hanya jika kedua bit sumber berbeda (hasil 6 = 0110).
Operator << dan >> menggeser seluruh bit: 12 << 2 menggeser 1100 dua posisi ke kiri menjadi 110000 (yaitu 48), setara dengan dikali 2**2. Sebaliknya, 12 >> 2 menggeser bit ke kanan menjadi 11 (yaitu 3), setara dengan floor division oleh 2**2.
Praktik: Flag Izin dengan Bitmask #
Penggunaan bitwise yang paling umum adalah flag: setiap bit mewakili satu pilihan aktif/tidak aktif. Kita kombinasikan flag dengan |, periksa dengan &, nyalakan dengan |=, dan matikan dengan &= ~:
BACA = 1 # 0b001
TULIS = 2 # 0b010
EKSEKUSI = 4 # 0b100
izin = BACA | TULIS
print("izin awal :", bin(izin))
print("cek BACA :", izin & BACA)
print("cek TULIS :", izin & TULIS)
print("cek EKSEKUSI :", izin & EKSEKUSI)
izin |= EKSEKUSI
print("tambah EKSEKUSI:", bin(izin))
izin &= ~TULIS
print("hapus TULIS :", bin(izin))Output yang Dihasilkan:
izin awal : 0b11
cek BACA : 1
cek TULIS : 2
cek EKSEKUSI : 0
tambah EKSEKUSI: 0b111
hapus TULIS : 0b101Mari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 1-3 (
BACA = 1dst.): setiap flag menempati satu bit berbeda —001,010,100— sehingga kombinasi keduanya tidak pernah saling menimpa. - Baris 5 (
izin = BACA | TULIS): operator|menyalakan bit pertama dan kedua sekaligus menghasilkan0b11(desimal3). - Baris 6-9 (
izin & BACAdst.): operator&menghasilkan nilai bukan nol jika flag tersebut aktif —1dan2menandakan aktif,0menandakan tidak. - Baris 11 (
izin |= EKSEKUSI): menyalakan bit ketiga tanpa mengubah bit lain;izinmenjadi0b111. - Baris 14 (
izin &= ~TULIS):~TULISmenghasilkan pola bit “semua satu kecuali bit kedua”, sehingga&menghapus hanya bit TULIS; hasilnya0b101.
Mengemas Nilai dengan Shift #
Operator shift memudahkan pengemasan beberapa nilai kecil menjadi satu bilangan besar. Warna pada layar tersimpan sebagai kombinasi merah, hijau, dan biru masing-masing 8 bit:
merah, hijau, biru = 202, 37, 71
warna = (merah << 16) | (hijau << 8) | biru
print("Nilai desimal:", warna)
print("Bentuk hex :", hex(warna))Output yang Dihasilkan:
Nilai desimal: 13247815
Bentuk hex : 0xca2547Pada baris warna = (merah << 16) | (hijau << 8) | biru, nilai merah digeser ke posisi bit 16-23, hijau ke bit 8-15, dan biru tetap di bit 0-7. Ketiganya digabung dengan | menjadi satu angka 13247815 yang ditampilkan fungsi hex() sebagai 0xca2547 — pasangan ca, 25, 47 justru adalah nilai merah, hijau, dan biru dalam heksadesimal.