Betrachten Sie diesen Code:
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
Ich kann die arithmetischen Operatoren in Python (und anderen Sprachen) verstehen, aber ich habe 'bitweise' Operatoren nie ganz gut verstanden. Im obigen Beispiel (aus einem Python-Buch) verstehe ich die Linksverschiebung, aber nicht die beiden anderen.
Wofür werden bitweise Operatoren tatsächlich verwendet? Ich würde einige Beispiele schätzen.
Antworten:
Bitweise Operatoren sind Operatoren, die mit Mehrbitwerten arbeiten, jedoch konzeptionell jeweils ein Bit.
AND
ist nur dann 1, wenn beide Eingänge 1 sind, andernfalls ist es 0.OR
ist 1, wenn einer oder beide Eingänge 1 sind, andernfalls ist es 0.XOR
ist nur dann 1, wenn genau einer seiner Eingänge 1 ist, andernfalls ist es 0.NOT
ist nur dann 1, wenn seine Eingabe 0 ist, andernfalls ist es 0.Diese können oft am besten als Wahrheitstabellen angezeigt werden. Die Eingabemöglichkeiten befinden sich oben und links. Das resultierende Bit ist einer der vier Werte (zwei im Fall von NOT, da es nur einen Eingang hat), die am Schnittpunkt der Eingänge angezeigt werden.
Ein Beispiel ist, wenn Sie nur die unteren 4 Bits einer ganzen Zahl wollen, Sie UND es mit 15 (binär 1111) also:
Die Nullbits in 15 wirken in diesem Fall effektiv als Filter und zwingen die Bits im Ergebnis, ebenfalls Null zu sein.
Darüber hinaus
>>
und<<
werden oft als Bit - Operatoren enthält, und sie „shift“ ein Wert jeweils rechts und durch eine bestimmte Anzahl von Bits nach links, Wegwerfen Bits , die Rolle des Endes in Richtung Sie Verschiebung und Fütterung in Null - Bits bei der anderes Ende.Also zum Beispiel:
Beachten Sie, dass die Linksverschiebung in Python insofern ungewöhnlich ist, als keine feste Breite verwendet wird, in der Bits verworfen werden. Während viele Sprachen eine feste Breite basierend auf dem Datentyp verwenden, erweitert Python die Breite einfach, um zusätzliche Bits zu berücksichtigen. Um das Verwerfungsverhalten in Python zu erhalten, können Sie eine Linksverschiebung mit einer bitweisen Verschiebung verfolgen,
and
z. B. bei einer 8-Bit-Wertverschiebung um vier Bit nach links:In diesem Sinne ist ein weiteres Beispiel für bitweise Operatoren: Wenn Sie zwei 4-Bit-Werte haben, die Sie in einen 8-Bit-Wert packen möchten, können Sie alle drei Operatoren (
left-shift
,and
undor
) verwenden:& 15
Operation stellt sicher, dass beide Werte nur die unteren 4 Bits haben.<< 4
ist eine 4-Bit-Verschiebung nach links, umval1
in die oberen 4 Bits eines 8-Bit-Werts zu gelangen.|
kombiniert diese beiden einfach miteinander.Wenn
val1
ist 7 undval2
ist 4:quelle
Eine typische Verwendung:
|
wird verwendet, um ein bestimmtes Bit auf 1 zu setzen&
wird verwendet, um ein bestimmtes Bit zu testen oder zu löschenSetzen Sie ein Bit (wobei n die Bitnummer und 0 das niedrigstwertige Bit ist):
unsigned char a |= (1 << n);
Klar ein bisschen:
unsigned char b &= ~(1 << n);
Ein bisschen umschalten:
unsigned char c ^= (1 << n);
Teste ein bisschen:
unsigned char e = d & (1 << n);
Nehmen Sie zum Beispiel den Fall Ihrer Liste:
x | 2
wird verwendet, um Bit 1 vonx
auf 1 zu setzenx & 1
wird verwendet, um zu testen, ob Bit 0 vonx
1 oder 0 istquelle
Eine der häufigsten Anwendungen von bitweisen Operationen ist das Parsen von hexadezimalen Farben.
Hier ist beispielsweise eine Python- Funktion, die einen String wie akzeptiert
#FF09BE
und ein Tupel ihrer Werte für Rot, Grün und Blau zurückgibt.Ich weiß, dass es effizientere Möglichkeiten gibt, dies zu erreichen, aber ich glaube, dass dies ein wirklich prägnantes Beispiel ist, das sowohl Verschiebungen als auch bitweise boolesche Operationen veranschaulicht.
quelle
Ich denke, dass der zweite Teil der Frage:
Wurde nur teilweise angesprochen. Das sind meine zwei Cent in dieser Angelegenheit.
Bitweise Operationen in Programmiersprachen spielen bei vielen Anwendungen eine grundlegende Rolle. Fast alle Low-Level-Berechnungen müssen mit dieser Art von Operationen durchgeführt werden.
In allen Anwendungen, die Daten zwischen zwei Knoten senden müssen, z.
Computernetzwerke;
Telekommunikationsanwendungen (Mobiltelefone, Satellitenkommunikation usw.).
In der unteren Kommunikationsebene werden die Daten normalerweise in sogenannten Frames gesendet . Frames sind nur Zeichenfolgen von Bytes, die über einen physischen Kanal gesendet werden. Diese Frames enthalten normalerweise die tatsächlichen Daten sowie einige andere Felder (in Bytes codiert), die Teil des sogenannten Headers sind . Der Header enthält normalerweise Bytes, die einige Informationen codieren, die sich auf den Status der Kommunikation beziehen (z. B. mit Flags (Bits)), Rahmenzählern, Korrektur- und Fehlererkennungscodes usw., um die übertragenen Daten in einem Rahmen abzurufen und die zu erstellen Frames, um Daten zu senden, benötigen Sie sicher bitweise Operationen.
Wenn Sie mit solchen Anwendungen arbeiten, steht im Allgemeinen eine API zur Verfügung, sodass Sie sich nicht mit all diesen Details befassen müssen. Beispielsweise bieten alle modernen Programmiersprachen Bibliotheken für Socket-Verbindungen, sodass Sie die TCP / IP-Kommunikationsrahmen nicht erstellen müssen. Aber denken Sie an die guten Leute, die diese APIs für Sie programmiert haben. Sie mussten sich mit Sicherheit mit der Rahmenkonstruktion befassen. Verwenden aller Arten von bitweisen Operationen, um von der Kommunikation auf niedriger Ebene zur Kommunikation auf höherer Ebene hin und her zu gelangen.
Stellen Sie sich als konkretes Beispiel vor, jemand gibt Ihnen eine Datei mit Rohdaten, die direkt von Telekommunikationshardware erfasst wurden. In diesem Fall müssen Sie zum Auffinden der Frames die Rohbytes in der Datei lesen und versuchen, Synchronisationswörter zu finden, indem Sie die Daten Stück für Stück scannen. Nachdem Sie die Synchronisationswörter identifiziert haben, müssen Sie die tatsächlichen Frames abrufen und sie bei Bedarf verschieben (und dies ist nur der Anfang der Geschichte), um die tatsächlichen Daten zu erhalten, die übertragen werden.
Eine andere, sehr unterschiedliche Anwendungsfamilie auf niedriger Ebene besteht darin, dass Sie die Hardware über einige (alte) Ports steuern müssen, z. B. parallele und serielle Ports. Diese Ports werden durch Setzen einiger Bytes gesteuert, und jedes Bit dieser Bytes hat in Bezug auf Anweisungen eine bestimmte Bedeutung für diesen Port (siehe zum Beispiel http://en.wikipedia.org/wiki/Parallel_port ). Wenn Sie Software erstellen möchten, die etwas mit dieser Hardware tut, benötigen Sie bitweise Operationen, um die Anweisungen, die Sie ausführen möchten, in die Bytes zu übersetzen, die der Port versteht.
Wenn Sie beispielsweise einige physische Tasten an den parallelen Anschluss angeschlossen haben, um ein anderes Gerät zu steuern, ist dies eine Codezeile, die Sie in der Soft-Anwendung finden:
Hoffe das trägt dazu bei.
quelle
Ich hoffe, das klärt diese beiden:
quelle
x & 1
veranschaulicht den Effekt nicht so gut wiex & 2
würde.Stellen Sie sich 0 als falsch und 1 als wahr vor. Dann funktionieren bitweise und (&) und oder (|) genau wie regulär und und oder, außer dass sie alle Bits im Wert gleichzeitig ausführen. In der Regel werden sie für Flags verwendet, wenn Sie über 30 Optionen verfügen, die festgelegt werden können (z. B. als Zeichenstile in einem Fenster). Sie möchten nicht 30 separate boolesche Werte übergeben müssen, um die einzelnen Werte festzulegen oder zu deaktivieren, sodass Sie | verwenden um Optionen zu einem einzigen Wert zu kombinieren und dann mit & zu prüfen, ob jede Option gesetzt ist. Diese Art der Flaggenübergabe wird von OpenGL häufig verwendet. Da jedes Bit ein separates Flag ist, erhalten Sie Flag-Werte für Zweierpotenzen (auch bekannt als Zahlen, bei denen nur ein Bit gesetzt ist). 1 (2 ^ 0) 2 (2 ^ 1) 4 (2 ^ 2) 8 (2 ^ 3) the Die Zweierpotenz gibt an, welches Bit gesetzt ist, wenn das Flag aktiviert ist.
Beachten Sie auch 2 = 10, so dass x | 2 110 (6) und nicht 111 (7) ist, wenn sich keines der Bits überlappt (was in diesem Fall zutrifft) | wirkt wie Addition.
quelle
Ich habe es oben nicht erwähnt, aber Sie werden auch sehen, dass einige Leute die Links- und Rechtsverschiebung für arithmetische Operationen verwenden. Eine Verschiebung nach links mit x entspricht dem Multiplizieren mit 2 ^ x (solange es nicht überläuft) und eine Verschiebung nach rechts entspricht dem Teilen durch 2 ^ x.
Kürzlich habe ich Leute gesehen, die x << 1 und x >> 1 zum Verdoppeln und Halbieren verwenden, obwohl ich nicht sicher bin, ob sie nur versuchen, klug zu sein, oder ob es wirklich einen deutlichen Vorteil gegenüber den normalen Operatoren gibt.
quelle
Sets
Mengen können mit mathematischen Operationen kombiniert werden.
|
kombiniert zwei Sätze zu einem neuen, der Elemente enthält.&
erhält nur Elemente in beiden.-
erhält Elemente im ersten Satz, jedoch nicht im zweiten.^
erhält Elemente in beiden Sätzen, jedoch nicht in beiden.Versuch es selber:
Ergebnis:
quelle
Dieses Beispiel zeigt Ihnen die Operationen für alle vier 2-Bit-Werte:
Hier ist ein Anwendungsbeispiel:
quelle
Ein weiterer häufiger Anwendungsfall ist das Bearbeiten / Testen von Dateiberechtigungen. Siehe das Python-Statistikmodul: http://docs.python.org/library/stat.html .
Um beispielsweise die Berechtigungen einer Datei mit einem gewünschten Berechtigungssatz zu vergleichen, können Sie Folgendes tun:
Ich habe die Ergebnisse als Boolesche Werte gewertet, weil mir nur die Wahrheit oder Falschheit wichtig ist, aber es wäre eine lohnende Übung, die bin () -Werte für jeden einzelnen auszudrucken.
quelle
not bool((mode ^ desired_mode) & 0777)
. Oder (leichter zu verstehen) :not (mode & 0777) ^ desired_mode == 0
. UND hinterlässt nur interessante Bits, XOR prüft, ob alle gewünschten Bits gesetzt sind. Expliziter== 0
Vergleich ist sinnvoller alsbool()
.setWindowFlags
. Beispiel :setWindowFlags(SplashScreen | WindowStaysOnTopHint)
. Ich finde das immer noch verwirrend, da es wie ein Umschalter erscheint, den Sie auf "Ein" setzen, so dass es in einem solchen Fall intuitiver zu "und" erscheint.Bitdarstellungen von Ganzzahlen werden im wissenschaftlichen Rechnen häufig verwendet, um Arrays von True-False-Informationen darzustellen, da eine bitweise Operation viel schneller ist als das Durchlaufen eines Arrays von Booleschen Werten. (Höhere Sprachen verwenden möglicherweise die Idee eines Bit-Arrays.)
Ein schönes und ziemlich einfaches Beispiel dafür ist die allgemeine Lösung für das Spiel Nim. Schauen Sie sich den Python- Code auf der Wikipedia-Seite an . Es nutzt stark bitweise exklusiv oder ,
^
.quelle
Es gibt möglicherweise einen besseren Weg, um herauszufinden, wo sich ein Array-Element zwischen zwei Werten befindet. Wie dieses Beispiel zeigt, funktioniert das & hier, wohingegen und nicht.
quelle
Ich habe es nicht erwähnt gesehen. Dieses Beispiel zeigt Ihnen die (-) Dezimaloperation für 2-Bit-Werte: AB (nur wenn A B enthält)
Diese Operation wird benötigt, wenn wir in unserem Programm ein Verb halten, das Bits darstellt. manchmal müssen wir Bits hinzufügen (wie oben) und manchmal müssen wir Bits entfernen (wenn das Verb dann enthält)
mit Python: 7 & ~ 4 = 3 (entferne von 7 die Bits, die 4 darstellen)
mit Python: 1 & ~ 4 = 1 (entferne von 1 die Bits, die 4 darstellen - in diesem Fall ist 1 nicht 'enthält' 4).
quelle
Während das Manipulieren von Bits einer Ganzzahl nützlich ist, kann es häufig für Netzwerkprotokolle, die bis auf das Bit spezifiziert werden können, das Manipulieren längerer Byte-Sequenzen erfordern (die nicht einfach in eine Ganzzahl konvertiert werden können). In diesem Fall ist es nützlich, die Bitstring- Bibliothek zu verwenden, die bitweise Operationen an Daten ermöglicht - z. B. kann man die Zeichenfolge 'ABCDEFGHIJKLMNOPQ' als Zeichenfolge oder als Hex- und Bitverschiebung importieren (oder andere bitweise Operationen ausführen):
quelle
die folgenden bitweisen Operatoren: & , | , ^ und ~ geben Werte (basierend auf ihrer Eingabe) auf die gleiche Weise zurück, wie Logikgatter Signale beeinflussen. Sie können sie verwenden, um Schaltkreise zu emulieren.
quelle
Um Bits umzudrehen (dh das Komplement / Invertieren von 1), können Sie Folgendes tun:
Da der Wert ExORed mit allen Einsen zur Inversion führt, können Sie sie für eine bestimmte Bitbreite mit ExOR invertieren.
quelle