Bitowe działanie i użycie

Rozważ ten kod:

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

Mogę zrozumieć operatory arytmetyczne w Pythonie (i innych językach), Ale nigdy nie rozumiałem operatorów 'bitowych' całkiem dobrze. W powyższym przykładzie (z książki Pythona) Rozumiem przesunięcie w lewo, ale nie dwa pozostałe.

Do czego właściwie służą operatory bitowe? Byłbym wdzięczny za kilka przykładów.

Author: Peter Mortensen, 2009-11-17

15 answers

Operatory bitowe to operatory, które działają na wartościach wielobitowych, ale koncepcyjnie jeden bit na raz.

  • AND jest 1 tylko wtedy, gdy oba jego wejścia są 1, w przeciwnym razie jest to 0.
  • OR jest 1, jeśli jeden lub oba jego wejścia są 1, w przeciwnym razie jest to 0.
  • XOR jest 1 tylko wtedy, gdy dokładnie jeden z jego wejść wynosi 1, w przeciwnym razie wynosi 0.
  • NOT jest 1 tylko wtedy, gdy jego wejście jest 0, w przeciwnym razie jest 0.

Te często mogą być najlepsze ukazane jako tablice prawdy. Możliwości wejściowe znajdują się na górze i po lewej stronie, Bit wynikowy jest jedną z czterech (dwóch w przypadku NOT, ponieważ ma tylko jedno wejście) wartości pokazanych na przecięciu wejść.

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

Jednym z przykładów jest to, że jeśli chcesz tylko niższe 4 bity liczby całkowitej, ty i to z 15 (binarne 1111) tak:

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

Bity zerowe w 15 W Tym Przypadku skutecznie działają jak filtr, zmuszając bity w wyniku do zera, jak również.

Dodatkowo, >> i << są często włączane jako operatory bitowe i "przesuwają" wartość odpowiednio w prawo i w lewo o określoną liczbę bitów, odrzucając bity, które obracają się na końcu, do którego się przesuwasz, i karmiąc bitami zerowymi na drugim końcu.

Więc, na przykład:

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

Zauważ, że przesunięcie w lewo w Pythonie jest niezwykłe, ponieważ nie używa stałej szerokości, gdzie bity są odrzucane - podczas gdy wiele języków używa stałej szerokości w oparciu o typ danych, Python po prostu rozszerza szerokość do zaspokoić dodatkowe kawałki. Aby uzyskać zachowanie odrzucania w Pythonie, możesz wykonać przesunięcie w lewo za pomocą bitowego and, np. w 8-bitowym przesunięciu wartości w lewo o cztery bity:

bits8 = (bits8 << 4) & 255

Mając to na uwadze, innym przykładem operatorów bitowych jest to, że jeśli masz dwie wartości 4-bitowe, które chcesz spakować do 8-bitowej, możesz użyć wszystkich trzech operatorów (left-shift, and oraz or):

packed_val = ((val1 & 15) << 4) | (val2 & 15)
  • operacja & 15 upewni się, że obie wartości mają tylko niższe 4 bity.
  • << 4 jest 4-bitowym przesunięciem w lewo, aby przenieść val1 do górnych 4 bitów o wartości 8-bitowej.
  • | po prostu łączy te dwie rzeczy razem.

Jeśli val1 jest 7 i val2 jest 4:

                val1            val2
                ====            ====
 & 15 (and)   xxxx-0111       xxxx-0100  & 15
 << 4 (left)  0111-0000           |
                  |               |
                  +-------+-------+
                          |
| (or)                0111-0100
 133
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 21:36:27

Jedno typowe użycie:

| jest używany do ustawiania określonego bitu na 1

& jest używany do testowania lub wyczyszczenia określonego bitu

  • Ustaw bit (gdzie n jest liczbą bitów, a 0 jest najmniej znaczącym bitem):

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

  • Wyczyść bit:

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

  • Przełącz trochę:

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

  • Przetestuj trochę:

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

Weź sprawę swojej listy dla przykład:

x | 2 jest używany do Ustawienia bitu 1 z x na 1

x & 1 jest używany do testowania, czy bit 0 z x wynosi 1 lub 0

 36
Author: pierrotlefou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-25 12:43:11

Do czego właściwie służą operatory bitowe? Byłbym wdzięczny za kilka przykładów.

Jednym z najczęstszych zastosowań operacji bitowych jest parsowanie kolorów szesnastkowych.

Na przykład, oto Funkcja Pythona, która przyjmuje ciąg znaków jak #FF09BE i zwraca krotkę jego czerwonych, zielonych i niebieskich wartości.

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)

Wiem, że są bardziej skuteczne sposoby, aby to osiągnąć, ale uważam, że jest to naprawdę zwięzły przykład ilustrujący obie zmiany i bitowe operacje logiczne.

 33
Author: bguiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-18 21:58:23

Myślę, że druga część pytania:

Do czego właściwie służą operatory bitowe? Byłbym wdzięczny za kilka przykładów.

Została rozwiązana tylko częściowo. To są moje dwa centy w tej sprawie.

Operacje bitowe w językach programowania odgrywają zasadniczą rolę w przypadku wielu aplikacji. Prawie wszystkie obliczenia niskiego poziomu muszą być wykonywane przy użyciu tego rodzaju operacji.

We wszystkich aplikacjach, które muszą wysyłać dane pomiędzy dwoma węzłami, np.:

  • Sieci Komputerowe;

  • Aplikacje telekomunikacyjne (telefony komórkowe, łączność satelitarna itp.).

W dolnej warstwie komunikacji dane są zazwyczaj przesyłane w tzw. ramkach . Ramki są po prostu ciągami bajtów wysyłanymi przez kanał fizyczny. Ramki te zazwyczaj zawierają rzeczywiste dane oraz inne pola (zakodowane w bajtach), które są częścią tego, co nazywa się nagłówek. Nagłówek zazwyczaj zawiera bajty kodujące pewne informacje związane ze stanem komunikacji (np. flagami (bitami)), licznikami ramek, kodami korekcji i wykrywania błędów, itp. Aby uzyskać przesyłane dane w ramce i zbudować ramki do wysyłania danych, musisz na pewno operacje bitowe.

Ogólnie rzecz biorąc, gdy mamy do czynienia z tego rodzaju aplikacjami, dostępne jest API, dzięki czemu nie musisz zajmować się wszystkimi tymi szczegółami. Na przykład, wszystkie nowoczesne języki programowania zapewniają biblioteki dla połączeń z gniazdami, więc nie trzeba budować ramek komunikacyjnych TCP / IP. Ale pomyśl o dobrych ludziach, którzy zaprogramowali te API dla Ciebie, na pewno mieli do czynienia z konstrukcją ramy; używając wszelkiego rodzaju operacji bitowych, aby przejść tam iz powrotem od komunikacji niskiego poziomu do komunikacji wyższego poziomu.

Jako konkretny przykład, wyobraź sobie, że ktoś daje Ci plik zawierający surowe dane, które zostały przechwycone bezpośrednio przez sprzęt telekomunikacyjny. W takim przypadku, aby znaleźć ramki, musisz przeczytać surowe bajty w pliku i spróbować znaleźć jakieś słowa synchronizacji, skanując dane bit po bitach. Po zidentyfikowaniu słów synchronizacji, będziesz musiał pobrać rzeczywiste klatki i przesunąć je, jeśli to konieczne (a to dopiero początek historii), aby uzyskać rzeczywiste dane, które są przesyłane.

Inną bardzo różną rodziną aplikacji niskiego poziomu jest wtedy, gdy musisz sterować sprzętem za pomocą niektórych (rodzaj starożytnych) portów, takich jak porty równoległe i szeregowe. Porty te są kontrolowane przez ustawienie niektórych bajtów, a każdy bit tego bajtu ma określone znaczenie, pod względem instrukcji, dla tego portu (patrz na przykład http://en.wikipedia.org/wiki/Parallel_port ). jeśli chcesz zbudować oprogramowanie, które robi coś z tym sprzętem, będziesz potrzebował operacji bitowych, aby przetłumaczyć instrukcje, które chcesz wykonać na bajty, które port Rozumiem.

Na przykład, jeśli masz fizyczne przyciski podłączone do portu równoległego, aby sterować innym urządzeniem, jest to linia kodu, którą możesz znaleźć w aplikacji soft:

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

Mam nadzieję, że to pomoże.

 7
Author: eguaio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 17:19:46

Mam nadzieję, że to wyjaśni te dwie rzeczy:

x | 2

0001 //x
0010 //2

0011 //result = 3

x & 1

0001 //x
0001 //1

0001 //result = 1
 6
Author: Amarghosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-25 12:43:32

Myśl o 0 jako false I 1 jako true. Następnie bitowe and(&) I or(|) działają tak samo jak zwykłe and and or, z wyjątkiem tego, że wykonują wszystkie bity w wartości naraz. Zazwyczaj zobaczysz je używane dla FLAG, jeśli masz 30 opcji, które można ustawić (powiedzmy jako style rysowania w oknie), nie chcesz przekazywać 30 oddzielnych wartości logicznych, aby ustawić lub wyłączyć każdą z nich, więc używasz | aby połączyć opcje w jedną wartość, a następnie używasz&, aby sprawdzić, czy każda opcja jest ustawiona. Ten styl przekazywania flagi jest mocno używany przez OpenGL. Ponieważ każdy bit jest osobną flagą, można uzyskać wartości flag na potęgach dwóch (czyli liczbach, które mają ustawiony tylko jeden bit) 1(2^0) 2(2^1) 4(2^2) 8(2^3) moc dwóch mówi, który bit jest ustawiony, jeśli flaga jest włączona.

Zauważ również, że 2 = 10, więc x|2 jest 110(6), a nie 111 (7), Jeśli żaden z bitów nie pokrywa się(co jest prawdą w tym przypadku) | działa jak dodawanie.

 5
Author: stonemetal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-17 05:05:21

Nie widziałem tego wyżej, ale zobaczysz również, że niektórzy ludzie używają lewego i prawego shift do operacji arytmetycznych. Przesunięcie w lewo przez x jest równoważne mnożeniu przez 2^x (o ile nie przepełnia się), a przesunięcie w prawo jest równoważne dzieleniu przez 2^x.

Ostatnio widziałem ludzi używających x > 1 do podwajania i zmniejszania o połowę, chociaż nie jestem pewien, czy po prostu próbują być sprytni, czy naprawdę istnieje wyraźna przewaga nad normalnymi operatorami.

 4
Author: P. Stallworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-15 01:11:07

Ten przykład pokaże operacje dla wszystkich czterech wartości 2-bitowych:

10 | 12

1010 #decimal 10
1100 #decimal 12

1110 #result = 14

10 & 12

1010 #decimal 10
1100 #decimal 12

1000 #result = 8

Oto przykład użycia:

x = raw_input('Enter a number:')
print 'x is %s.' % ('even', 'odd')[x&1]
 3
Author: dansalmo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 01:41:35

Innym powszechnym przypadkiem użycia jest manipulowanie / testowanie uprawnień do plików. Zobacz moduł stat Pythona: http://docs.python.org/library/stat.html .

Na przykład, aby porównać uprawnienia pliku z żądanym zestawem uprawnień, możesz zrobić coś takiego:

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)

Rzucam wyniki jako booleany, ponieważ dbam tylko o prawdę lub FAŁSZ, ale warto byłoby wydrukować wartości bin() dla każdego z nich.

 2
Author: dbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-08 20:29:34

Bitowe reprezentacje liczb całkowitych są często używane w komputerach naukowych do reprezentowania tablic informacji prawda-fałsz, ponieważ operacja bitowa jest znacznie szybsza niż iteracja przez tablicę logicznych. (Języki wyższego poziomu mogą używać idei tablicy bitów.)

Miłym i dość prostym tego przykładem jest ogólne rozwiązanie gry Nim. Spójrz na kod Pythona na stronie Wikipedii . Wykorzystuje w dużym stopniu bitowe exclusive or, ^.
 2
Author: Jonah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-25 12:46:15

Może być lepszy sposób, aby znaleźć, gdzie element tablicy znajduje się między dwiema wartościami, ale jak pokazuje ten przykład,& działa tutaj, natomiast oraz nie.

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]),)
 1
Author: woodfoot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-22 19:42:50

Nie widziałem, jak to wspomniano, ten przykład pokaże Ci (-) operację dziesiętną dla wartości 2 bitowych: A-B (tylko jeśli a Zawiera B)

Ta operacja jest potrzebna, gdy posiadamy w naszym programie czasownik, który reprezentuje bity. czasami musimy dodać bity (jak wyżej), a czasami musimy usunąć bity (jeśli czasownik zawiera then)

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

Z Pythonem: 7 & ~4 = 3 (Usuń z 7 bitów, które reprezentują 4)

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

Z Pythonem: 1 & ~4 = 1 (usunąć bity reprezentujące 4 - w tym przypadku 1 nie jest' zawiera ' 4)..

 1
Author: Eyal Ch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-20 21:03:30

Zestawy

Zbiory mogą być łączone za pomocą operacji matematycznych.

  • operator Unii | łączy dwa zestawy, tworząc nowy, zawierający elementy w każdym z nich.
  • operator przecięcia & pobiera elementy tylko w obu.
  • operator różnicy - pobiera elementy w pierwszym zbiorze, ale nie w drugim.
  • Operator różnicy symetrycznej ^ pobiera elementy w każdym zbiorze, ale nie w obu.

Spróbuj Yourself:

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)

Wynik:

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

{4, 5, 6}

{1, 2, 3}

{8, 9, 7}

{1, 2, 3, 7, 8, 9}
 1
Author: PUNEET JAIN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-24 13:42:15

Podczas gdy manipulowanie bitami liczby całkowitej jest przydatne, często dla protokołów sieciowych, które mogą być określone w dół do bitu, można wymagać manipulacji dłuższymi sekwencjami bajtów (które nie są łatwo przekonwertowane na jedną liczbę całkowitą). W tym przypadku przydatne jest użycie biblioteki bitstring , która pozwala na operacje bitowe na danych - np. można importować łańcuch 'ABCDEFGHIJKLMNOPQ' jako łańcuch lub jako hex i przesuwać go (lub wykonywać inne operacje bitowe):

>>> import bitstring
>>> bitstring.BitArray(bytes='ABCDEFGHIJKLMNOPQ') << 4
BitArray('0x142434445464748494a4b4c4d4e4f50510')
>>> bitstring.BitArray(hex='0x4142434445464748494a4b4c4d4e4f5051') << 4
BitArray('0x142434445464748494a4b4c4d4e4f50510')
 0
Author: Pierz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-12 09:27:02

Następujące operatory bitowe: &, |, ^, oraz ~ zwracane wartości (na podstawie ich wejścia) w ten sam sposób bramki logiczne wpływają na sygnały. Możesz ich użyć do naśladowania obwodów.

 0
Author: Erik Waters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-02 15:05:32