Operasi dan penggunaan bitwise

102

Pertimbangkan kode ini:

x = 1        # 0001
x << 2       # Shift left 2 bits: 0100
# Result: 4

x | 2        # Bitwise OR: 0011
# Result: 3

x & 1        # Bitwise AND: 0001
# Result: 1

Saya dapat memahami operator aritmatika dengan Python (dan bahasa lain), tetapi saya tidak pernah memahami operator 'bitwise' dengan cukup baik. Dalam contoh di atas (dari buku Python), saya memahami pergeseran kiri tetapi bukan dua lainnya.

Juga, untuk apa sebenarnya operator bitwise digunakan? Saya menghargai beberapa contoh.

eozzy
sumber

Jawaban:

163

Operator bitwise adalah operator yang mengerjakan nilai multi-bit, tetapi secara konseptual satu bit pada satu waktu.

  • ANDbernilai 1 hanya jika kedua masukannya adalah 1, jika tidak maka 0.
  • ORbernilai 1 jika salah satu atau kedua inputnya adalah 1, jika tidak maka 0.
  • XORbernilai 1 hanya jika salah satu inputnya adalah 1, jika tidak maka 0.
  • NOT bernilai 1 hanya jika inputnya 0, jika tidak maka 0.

Ini sering kali paling baik ditampilkan sebagai tabel kebenaran. Kemungkinan masukan ada di atas dan kiri, bit resultan adalah salah satu dari empat (dua dalam kasus NOT karena hanya memiliki satu masukan) nilai yang ditampilkan di persimpangan masukan.

AND | 0 1     OR | 0 1     XOR | 0 1    NOT | 0 1
----+-----    ---+----     ----+----    ----+----
 0  | 0 0      0 | 0 1       0 | 0 1        | 1 0
 1  | 0 1      1 | 1 1       1 | 1 0

Salah satu contohnya adalah jika Anda hanya menginginkan 4 bit yang lebih rendah dari sebuah integer, Anda DAN dengan 15 (biner 1111) jadi:

    201: 1100 1001
AND  15: 0000 1111
------------------
 IS   9  0000 1001

Bit nol dalam 15 dalam hal itu secara efektif bertindak sebagai filter, memaksa bit dalam hasil menjadi nol juga.

Selain itu, >>dan <<sering kali disertakan sebagai operator bitwise, dan mereka "menggeser" nilai masing-masing ke kanan dan kiri dengan sejumlah bit tertentu, membuang bit yang menggulung ujung yang Anda tuju, dan memasukkan bit nol di ujung lainnya.

Jadi, misalnya:

1001 0101 >> 2 gives 0010 0101
1111 1111 << 4 gives 1111 0000

Perhatikan bahwa pergeseran kiri di Python tidak biasa karena tidak menggunakan lebar tetap di mana bit dibuang - sementara banyak bahasa menggunakan lebar tetap berdasarkan tipe datanya, Python hanya memperluas lebar untuk memenuhi bit tambahan. Untuk mendapatkan perilaku membuang dengan Python, Anda dapat mengikuti pergeseran kiri dengan bitwise andseperti pada nilai 8-bit yang bergeser ke kiri empat bit:

bits8 = (bits8 << 4) & 255

Dengan pemikiran tersebut, contoh lain dari operator bitwise adalah jika Anda memiliki dua nilai 4-bit yang ingin Anda masukkan ke dalam nilai 8-bit, Anda dapat menggunakan ketiga operator Anda ( left-shift, anddan or):

packed_val = ((val1 & 15) << 4) | (val2 & 15)
  • The & 15operasi akan memastikan bahwa kedua nilai hanya memiliki lebih rendah 4 bit.
  • Ini << 4adalah pergeseran 4-bit ke kiri untuk pindah val1ke 4 bit teratas dari nilai 8-bit.
  • Secara |sederhana menggabungkan keduanya.

Jika val17 dan val24:

                val1            val2
                ====            ====
 & 15 (and)   xxxx-0111       xxxx-0100  & 15
 << 4 (left)  0111-0000           |
                  |               |
                  +-------+-------+
                          |
| (or)                0111-0100
paxdiablo
sumber
43

Satu penggunaan tipikal:

| digunakan untuk menyetel bit tertentu ke 1

& digunakan untuk menguji atau menghapus bit tertentu

  • Tetapkan sedikit (di mana n adalah nomor bit, dan 0 adalah bit paling signifikan):

    unsigned char a |= (1 << n);

  • Hapus sedikit:

    unsigned char b &= ~(1 << n);

  • Beralih sedikit:

    unsigned char c ^= (1 << n);

  • Uji sedikit:

    unsigned char e = d & (1 << n);

Ambil kasus daftar Anda misalnya:

x | 2digunakan untuk mengatur bit 1 dari x1

x & 1digunakan untuk menguji apakah bit 0 dari x1 atau 0

pierrotlefou.dll
sumber
38

untuk apa sebenarnya operator bitwise digunakan? Saya menghargai beberapa contoh.

Salah satu kegunaan paling umum dari operasi bitwise adalah untuk mengurai warna heksadesimal.

Misalnya, inilah fungsi Python yang menerima string like #FF09BEdan mengembalikan tupel nilai Merah, Hijau dan Biru.

def hexToRgb(value):
    # Convert string to hexadecimal number (base 16)
    num = (int(value.lstrip("#"), 16))

    # Shift 16 bits to the right, and then binary AND to obtain 8 bits representing red
    r = ((num >> 16) & 0xFF)

    # Shift 8 bits to the right, and then binary AND to obtain 8 bits representing green
    g = ((num >> 8) & 0xFF)

    # Simply binary AND to obtain 8 bits representing blue
    b = (num & 0xFF)
    return (r, g, b)

Saya tahu bahwa ada cara yang lebih efisien untuk mencapai hal ini, tetapi saya yakin ini adalah contoh yang sangat ringkas yang mengilustrasikan operasi shift dan bitwise boolean.

bguiz
sumber
14

Saya pikir bagian kedua dari pertanyaan itu:

Juga, untuk apa sebenarnya operator bitwise digunakan? Saya menghargai beberapa contoh.

Hanya ditangani sebagian. Ini adalah dua sen saya untuk masalah itu.

Operasi bitwise dalam bahasa pemrograman memainkan peran mendasar saat menangani banyak aplikasi. Hampir semua komputasi tingkat rendah harus dilakukan dengan menggunakan operasi semacam ini.

Di semua aplikasi yang perlu mengirim data antara dua node, seperti:

  • jaringan komputer;

  • aplikasi telekomunikasi (telepon seluler, komunikasi satelit, dll).

Pada lapisan komunikasi tingkat bawah, data biasanya dikirim dalam apa yang disebut bingkai . Bingkai hanyalah string byte yang dikirim melalui saluran fisik. Bingkai ini biasanya berisi data aktual ditambah beberapa bidang lain (dikodekan dalam byte) yang merupakan bagian dari apa yang disebut tajuk . Header biasanya berisi byte yang menyandikan beberapa informasi yang berkaitan dengan status komunikasi (misalnya, dengan bendera (bit)), penghitung bingkai, kode koreksi dan deteksi kesalahan, dll. Untuk mendapatkan data yang dikirimkan dalam bingkai, dan untuk membangun frame untuk mengirim data, Anda akan memerlukan operasi bitwise pasti.

Secara umum, ketika menangani aplikasi semacam itu, API tersedia sehingga Anda tidak perlu berurusan dengan semua detail itu. Misalnya, semua bahasa pemrograman modern menyediakan pustaka untuk koneksi soket, jadi Anda sebenarnya tidak perlu membuat bingkai komunikasi TCP / IP. Tetapi pikirkan tentang orang-orang baik yang memprogram API tersebut untuk Anda, mereka pasti berurusan dengan konstruksi bingkai; menggunakan semua jenis operasi bitwise untuk bolak-balik dari komunikasi tingkat rendah ke tingkat yang lebih tinggi.

Sebagai contoh konkret, bayangkan seseorang memberi Anda file yang berisi data mentah yang ditangkap langsung oleh perangkat keras telekomunikasi. Dalam hal ini, untuk menemukan bingkai, Anda perlu membaca byte mentah dalam file dan mencoba menemukan beberapa jenis kata sinkronisasi, dengan memindai data sedikit demi sedikit. Setelah mengidentifikasi kata-kata sinkronisasi, Anda perlu mendapatkan bingkai sebenarnya, dan SHIFT jika perlu (dan itu baru permulaan cerita) untuk mendapatkan data aktual yang sedang dikirim.

Kelompok aplikasi tingkat rendah lain yang sangat berbeda adalah ketika Anda perlu mengontrol perangkat keras menggunakan beberapa port (jenis kuno), seperti port paralel dan serial. Porta ini dikontrol dengan mengatur beberapa byte, dan setiap bit dari byte tersebut memiliki arti khusus, dalam hal instruksi, untuk port tersebut (lihat misalnya http://en.wikipedia.org/wiki/Parallel_port ). Jika Anda ingin membangun perangkat lunak yang melakukan sesuatu dengan perangkat keras tersebut, Anda memerlukan operasi bitwise untuk menerjemahkan instruksi yang ingin Anda jalankan ke byte yang dipahami oleh port.

Misalnya, jika Anda memiliki beberapa tombol fisik yang terhubung ke port paralel untuk mengontrol beberapa perangkat lain, ini adalah baris kode yang dapat Anda temukan di aplikasi lunak:

read = ((read ^ 0x80) >> 4) & 0x0f; 

Semoga ini berkontribusi.

eguaio
sumber
Saya akan menambahkan en.wikipedia.org/wiki/Bit_banging sebagai jalan lain untuk dijelajahi terutama jika membaca tentang port paralel dan serial sebagai contoh di mana operasi bitwise dapat berguna.
Dan
6

Saya harap ini menjelaskan keduanya:

x | 2

0001 //x
0010 //2

0011 //result = 3

x & 1

0001 //x
0001 //1

0001 //result = 1
Amarghosh
sumber
4
Ups ... mencoba menjadi senjata tercepat di barat .... berakhir sebagai idiot yang bahkan tidak tahu biner untuk dua :( Diperbaiki.
Amarghosh
1
x & 1tidak menggambarkan efek sebaik yang x & 2akan terjadi.
dansalmo
5

Pikirkan 0 sebagai salah dan 1 sebagai benar. Kemudian bitwise dan (&) dan atau (|) bekerja seperti biasa dan dan atau kecuali mereka melakukan semua bit dalam nilai sekaligus. Biasanya Anda akan melihatnya digunakan untuk flag jika Anda memiliki 30 opsi yang dapat disetel (katakanlah sebagai gaya gambar di jendela) Anda tidak ingin harus meneruskan 30 nilai boolean terpisah untuk menyetel atau membatalkan setelan masing-masing sehingga Anda menggunakan | untuk menggabungkan opsi menjadi satu nilai dan kemudian Anda menggunakan & untuk memeriksa apakah setiap opsi disetel. Gaya pengoperan bendera ini banyak digunakan oleh OpenGL. Karena setiap bit adalah bendera terpisah Anda mendapatkan nilai bendera pada pangkat dua (alias angka yang hanya memiliki satu set bit) 1 (2 ^ 0) 2 (2 ^ 1) 4 (2 ^ 2) 8 (2 ^ 3) power of two memberi tahu Anda bit mana yang disetel jika flag aktif.

Perhatikan juga 2 = 10 jadi x | 2 adalah 110 (6) bukan 111 (7) Jika tidak ada bit yang tumpang tindih (yang benar dalam kasus ini) | bertindak seperti penambahan.

stonemetal
sumber
5

Saya tidak melihatnya disebutkan di atas tetapi Anda juga akan melihat beberapa orang menggunakan shift kiri dan kanan untuk operasi aritmatika. Pergeseran kiri sebesar x sama dengan mengalikan dengan 2 ^ x (selama tidak meluap) dan pergeseran kanan setara dengan membagi dengan 2 ^ x.

Baru-baru ini saya telah melihat orang menggunakan x << 1 dan x >> 1 untuk menggandakan dan membagi dua, meskipun saya tidak yakin apakah mereka hanya mencoba untuk menjadi pintar atau apakah benar-benar ada keuntungan yang berbeda dibandingkan operator normal.

P. Stallworth
sumber
1
Saya tidak tahu tentang python, tetapi dalam bahasa tingkat rendah seperti C atau bahkan perakitan yang lebih rendah, pergeseran bitwise jauh lebih efisien. Untuk melihat perbedaannya, Anda dapat menulis program dalam C dengan cara masing-masing dan hanya mengkompilasi ke kode assembly (atau jika Anda tahu bahasa assembly, Anda pasti sudah mengetahui ini :)). Lihat perbedaan jumlah instruksi.
0xc0de
2
Argumen saya menentang penggunaan operator bit shift adalah bahwa sebagian besar kompiler modern mungkin sudah mengoptimalkan operasi aritmatika sehingga kepintarannya diperdebatkan atau paling buruk melawan kompiler. Saya tidak memiliki keahlian dalam C, kompiler, atau desain CPU, jadi jangan anggap saya benar. :)
P. Stallworth
Ini harus lebih tinggi. Saya harus berurusan dengan beberapa kode yang menggunakan operator bitwise persis seperti itu, dan jawaban itu membantu saya mencari tahu.
Philippe Oger
4

Set

Set dapat digabungkan menggunakan operasi matematika.

  • Operator serikat |menggabungkan dua set untuk membentuk yang baru berisi item di salah satunya.
  • Operator persimpangan &hanya mendapatkan item di keduanya.
  • Operator perbedaan -mendapat item di set pertama tetapi tidak di set kedua.
  • Operator perbedaan simetris ^mendapatkan item di salah satu set, tetapi tidak keduanya.

Cobalah sendiri:

first = {1, 2, 3, 4, 5, 6}
second = {4, 5, 6, 7, 8, 9}

print(first | second)

print(first & second)

print(first - second)

print(second - first)

print(first ^ second)

Hasil:

{1, 2, 3, 4, 5, 6, 7, 8, 9}

{4, 5, 6}

{1, 2, 3}

{8, 9, 7}

{1, 2, 3, 7, 8, 9}
PUNEET JAIN
sumber
Jawaban ini sama sekali tidak terkait dengan pertanyaan tersebut, dan tampaknya telah disalin dan ditempelkan dari tempat lain.
doctaphred
Pertanyaannya menanyakan "Untuk apa sebenarnya operator bitwise digunakan?". Jawaban ini memberikan penggunaan operator bitwise yang kurang dikenal tetapi sangat berguna.
Taegyung
3

Contoh ini akan menunjukkan operasi untuk keempat nilai 2 bit:

10 | 12

1010 #decimal 10
1100 #decimal 12

1110 #result = 14

10 & 12

1010 #decimal 10
1100 #decimal 12

1000 #result = 8

Ini salah satu contoh penggunaan:

x = raw_input('Enter a number:')
print 'x is %s.' % ('even', 'odd')[x&1]
dansalmo
sumber
2

Kasus penggunaan umum lainnya adalah memanipulasi / menguji izin file. Lihat modul stat Python: http://docs.python.org/library/stat.html .

Misalnya, untuk membandingkan izin file dengan satu set izin yang diinginkan, Anda dapat melakukan sesuatu seperti:

import os
import stat

#Get the actual mode of a file
mode = os.stat('file.txt').st_mode

#File should be a regular file, readable and writable by its owner
#Each permission value has a single 'on' bit.  Use bitwise or to combine 
#them.
desired_mode = stat.S_IFREG|stat.S_IRUSR|stat.S_IWUSR

#check for exact match:
mode == desired_mode
#check for at least one bit matching:
bool(mode & desired_mode)
#check for at least one bit 'on' in one, and not in the other:
bool(mode ^ desired_mode)
#check that all bits from desired_mode are set in mode, but I don't care about 
# other bits.
not bool((mode^desired_mode)&desired_mode)

Saya memberikan hasil sebagai boolean, karena saya hanya peduli tentang kebenaran atau kepalsuan, tetapi akan menjadi latihan yang bermanfaat untuk mencetak nilai bin () untuk masing-masing.

dbn
sumber
1
Anda salah dalam contoh terakhir. Berikut bagaimana seharusnya terlihat seperti: not bool((mode ^ desired_mode) & 0777). Atau (lebih mudah untuk memahami): not (mode & 0777) ^ desired_mode == 0. DAN hanya akan menyisakan bit yang menarik, XOR akan memeriksa semua bit yang diinginkan sudah disetel. == 0Perbandingan eksplisit lebih berarti daripada bool().
Vadim Fint
Saya tidak berpikir ini khusus untuk operasi file. Misalnya, di PyQt Anda melakukan sesuatu yang serupa setWindowFlags. Contoh: setWindowFlags(SplashScreen | WindowStaysOnTopHint). Saya masih menemukan ini membingungkan, karena sepertinya sakelar yang Anda atur ke 'on' sehingga tampak lebih intuitif untuk 'dan' dalam kasus seperti itu.
eric
2

Representasi bit bilangan bulat sering digunakan dalam komputasi ilmiah untuk merepresentasikan array informasi benar-salah karena operasi bitwise jauh lebih cepat daripada melakukan iterasi melalui array boolean. (Bahasa tingkat yang lebih tinggi mungkin menggunakan gagasan larik bit.)

Contoh yang bagus dan cukup sederhana dari ini adalah solusi umum untuk game Nim. Lihat kode Python di halaman Wikipedia . Itu membuat penggunaan bitwise eksklusif atau ^,.

Yunus
sumber
1

Mungkin ada cara yang lebih baik untuk menemukan di mana elemen array berada di antara dua nilai, tetapi seperti yang ditunjukkan contoh ini, & berfungsi di sini, sedangkan dan tidak.

import numpy as np
a=np.array([1.2, 2.3, 3.4])
np.where((a>2) and (a<3))      
#Result: Value Error
np.where((a>2) & (a<3))
#Result: (array([1]),)
kaki kayu
sumber
1

saya tidak melihatnya disebutkan, Contoh ini akan menunjukkan operasi desimal (-) untuk nilai 2 bit: AB (hanya jika A berisi B)

operasi ini diperlukan ketika kita memegang kata kerja dalam program kita yang mewakili bit. terkadang kita perlu menambahkan bit (seperti di atas) dan terkadang kita perlu menghapus bit (jika kata kerjanya mengandung)

111 #decimal 7
-
100 #decimal 4
--------------
011 #decimal 3

dengan python: 7 & ~ 4 = 3 (hapus dari 7 bit yang mewakili 4)

001 #decimal 1
-
100 #decimal 4
--------------
001 #decimal 1

dengan python: 1 & ~ 4 = 1 (hapus dari 1 bit yang mewakili 4 - dalam hal ini 1 tidak 'berisi' 4) ..

Eyal Ch
sumber
0

Sementara memanipulasi bit integer berguna, seringkali untuk protokol jaringan, yang dapat ditentukan hingga bit, seseorang dapat memerlukan manipulasi urutan byte yang lebih panjang (yang tidak mudah diubah menjadi satu integer). Dalam hal ini berguna untuk menggunakan pustaka bitstring yang memungkinkan operasi bitwise pada data - misalnya, seseorang dapat mengimpor string 'ABCDEFGHIJKLMNOPQ' sebagai string atau sebagai hex dan bit menggesernya (atau melakukan operasi bitwise lainnya):

>>> import bitstring
>>> bitstring.BitArray(bytes='ABCDEFGHIJKLMNOPQ') << 4
BitArray('0x142434445464748494a4b4c4d4e4f50510')
>>> bitstring.BitArray(hex='0x4142434445464748494a4b4c4d4e4f5051') << 4
BitArray('0x142434445464748494a4b4c4d4e4f50510')
Pierz
sumber
0

operator bitwise berikut: & , | , ^ , dan ~ mengembalikan nilai (berdasarkan masukannya) dengan cara yang sama gerbang logika memengaruhi sinyal. Anda dapat menggunakannya untuk meniru sirkuit.

Erik Waters
sumber
0

Untuk membalik bit (yaitu pelengkap / pembalik 1), Anda dapat melakukan hal berikut:

Karena nilai ExORed dengan semua hasil 1 menjadi inversi, untuk lebar bit tertentu Anda dapat menggunakan ExOR untuk membalikkannya.

In Binary
a=1010 --> this is 0xA or decimal 10
then 
c = 1111 ^ a = 0101 --> this is 0xF or decimal 15
-----------------
In Python
a=10
b=15
c = a ^ b --> 0101
print(bin(c)) # gives '0b101'
pengguna11034079
sumber