2015-02-10 13 views
16

Vor kurzem las ich golang Spezifikation und mit einigen interessanten Betreiber konfrontiert:Unterschied zwischen einigen Operatoren "|", "^", "&", "& ^". Golang

& bitwise AND   integers 
| bitwise OR    integers 
^ bitwise XOR   integers 
&^ bit clear (AND NOT) integers 

Ich habe versucht, mit ihm zu spielen, aber die einzige, die ich verstanden habe ist, dass „|“ addieren Sie Ganzzahlen und "+" Operator arbeiten zusätzlich mit Schwimmer, Strings usw.

Wofür werden sie in der Praxis eingesetzt? Könnte irgendjemand eine Erklärung zu diesen 4 Betreibern geben?

+2

Schnappen Sie sich ein Buch wie Petzolds "Code", um ein grundlegendes Verständnis der binären Darstellung und der Grundlagen des Computing zu erhalten. –

Antwort

30

Bitweise Operatoren kommen ins Spiel, wenn Sie mit Byte- oder Bit-Level-Daten arbeiten müssen.

Hier Liste ich eine Handvoll Beispiele Bit-Operationen mit Codebeispielen verwendet (in keiner bestimmten Reihenfolge):


1. Sie sind häufig und Bestandteil vieler Algorithmen in Kryptographie und Hash Funktionen (zB MD5).

2. Sie werden häufig auch verwendet, wenn Sie Raum zu „retten“ wollen, und Sie Pack mehr „Bool“ Variablen in eine int Sie zum Beispiel einen Bit jeden Bool Variablen zuweisen. Sie müssen bitweise Operatoren verwenden, um die Bits einzeln ändern/lesen zu können.

Zum Beispiel Verpackung 8 Bit/bools in einem int:

flags := 0x00 // All flags are 0 
flags |= 0x02 // Turn the 2nd bit to 1 (leaving rest unchanged) 
flags |= 0xff // Turn 8 bits (0..7) to 1 
flags &= 0xfe // Set the lowest bit to 0 (leaving rest unchanged) 

istrue := flags&0x04 != 0 // Test if 3rd bit is 1 

3. Ein weiterer Bereich ist Datenkomprimierungs, wo Sie das Beste aus einem byte erhalten möchten und alle seine Bits verwenden, um speichern/retreive einige Informationen (ein Bit ist die grundlegende Informationseinheit in der Computer- und digitalen Kommunikation).

4. Ähnlich wie die Komprimierung aber nicht ganz das Gleiche: bitstreams. Es wird auch verwendet, um Platz in einem Datenstrom zu sparen, indem keine vollständigen Bytes, sondern Felder mit beliebiger Bitlänge gesendet werden.

Ich habe ein hoch optimiertes Bit-Level-Reader- und Writer-Paket geschrieben und veröffentlicht, das hier veröffentlicht wurde: github.com/icza/bitio. In seinen Quellen wird eine umfangreiche Verwendung aller Arten von Bitoperationen angezeigt.

5. Eine weitere praktische Verwendung: Testen bestimmter Eigenschaften einer (ganzen) Zahl. Wenn man die binäre Darstellung von ganzen Zahlen kennt (Two's complement), gibt es bestimmte Eigenschaften von Zahlen in ihrer binären Darstellung. Zum Beispiel eine ganze Zahl (in 2-Komplement) ist sogar (kann durch 2 geteilt werden), wenn das niedrigste Bit 0:

func isEven(i int) bool { 
    return i&0x01 == 0 
} 

durch die Bits eines ganzzahligen Testen kann man auch sagen, ob es eine Leistung ist Wenn eine positive Zahl nur ein Bit 1 enthält, dann ist es eine Potenz von 2 (z2 = 0x02 = 00000010b, 16 = 0x10 = 00010000 aber zum Beispiel 17 = 0x11 = 00010001 nicht power von 2).

6.Viele Codierungs-/Decodierverfahren verwenden auch Bitoperationen. Am trivialsten ist die UTF-8 encoding, die eine Codierung mit variabler Länge zum Darstellen von Unicode-Codepunkten (rune in Go) als Bytefolgen verwendet.
Eine einfache Variante einer Codierung mit variabler Länge könnte sein, das höchste Bit eines Bytes (8. oder 7. wenn 0-indexiert) zu verwenden, um zu signalisieren, ob mehr Bytes benötigt werden, um eine Zahl zu decodieren, und die restlichen 7 Bits sind immer die "nützliche" Daten. Sie können die höchste Bit testen und zu „trennen“ die 7 Nutzbits wie folgt aus:

b := readOneByte() 
usefulBits := b & 0x7f 
hasMoreBytes := b & 0x80 != 0 

Der Gewinn der Verwendung eines solchen Codierung mit variabler Länge ist, dass selbst wenn Sie uint64 Typ in Go verwenden, die 8 Bytes im Speicher kleine Zahlen können immer noch mit weniger Bytes dargestellt werden (Zahlen im Bereich 0..127 benötigen nur 1 Byte!). Wenn die Samples, die Sie speichern oder übertragen möchten, viele kleine Werte haben, kann dies allein die Daten auf 1/8 = 12,5% komprimieren. Der Nachteil ist, dass große Zahlen (die Bits sogar im höchsten Byte haben) mehr als 8 Bytes verwenden werden. Ob es sich lohnt, hängt von der Heuristik der Samples ab.

X.Und die Liste geht weiter ...


Können Sie leben ohne zu wissen,/mit bitweise Operatoren in Go (und in vielen anderen Programmiersprachen)? Die Antwort ist ja. Aber wenn Sie sie kennen, können sie manchmal Ihr Leben einfacher und Ihre Programme effizienter machen.

Wenn Sie mehr über das Thema erfahren möchten, lesen Sie den Wikipedia-Artikel: Bitwise operation und google den Begriff "Bitwise Operators Tutorial", es gibt viele gute Artikel.

+0

Danke! Wirklich gute Antwort. Könntest du das Buch vorschlagen, das einige Grundlagen der "Low Level" Programmierung für Anfänger wie mich erklärt? (ohne in zu technische und mathematische Begriffe zu vertiefen) –

+1

@TimurFayzrakhmanov Einfach googeln (der Begriff _ "bitwise operators tutorial" _), es gibt viele gute Tutorials im Internet. Die meisten sind sprachspezifisch, gelten aber mehr oder weniger für alle Programmiersprachen. Hier ist eine gute in 1 Minute Googeln gefunden: [Bit Bit Operatoren verstehen] (http://code.tutsplus.com/articles/understanding-bitwise-operators--active-11301). Lesen Sie auch den Wikipedia-Artikel: [Bitwise Operation] (http://en.wikipedia.org/wiki/Bitwise_operation) – icza

+0

hab es geschafft! Nochmals vielen Dank!) –

13

Für das, was sie technisch die Kommentare prüfen in diesem

package main 

import "fmt" 

func main() { 
    // Use bitwise OR | to get the bits that are in 1 OR 2 
    // 1  = 00000001 
    // 2  = 00000010 
    // 1 | 2 = 00000011 = 3 
    fmt.Println(1 | 2) 

    // Use bitwise OR | to get the bits that are in 1 OR 5 
    // 1  = 00000001 
    // 5  = 00000101 
    // 1 | 5 = 00000101 = 5 
    fmt.Println(1 | 5) 

    // Use bitwise XOR^to get the bits that are in 3 OR 6 BUT NOT BOTH 
    // 3  = 00000011 
    // 6  = 00000110 
    // 3^6 = 00000101 = 5 
    fmt.Println(3^6) 

    // Use bitwise AND & to get the bits that are in 3 AND 6 
    // 3  = 00000011 
    // 6  = 00000110 
    // 3 & 6 = 00000010 = 2 
    fmt.Println(3 & 6) 

    // Use bit clear AND NOT &^ to get the bits that are in 3 AND NOT 6 (order matters) 
    // 3  = 00000011 
    // 6  = 00000110 
    // 3 &^ 6 = 00000001 = 1 
    fmt.Println(3 &^ 6) 
} 

View it on the playground

Bitte beachten Sie, dass ich zwei Beispiele für | gab zu zeigen, dass es nicht wirklich hinaus wie 1 + 5 ist.

Wie für die praktische Verwendung bin ich mir sicher, dass einige andere mit mehr Beispielen kommentieren könnten, aber eine allgemeine Verwendung ist es, eine Bitmaske von Flags für so etwas wie ein Berechtigungssystem zu erstellen.

Verwandte Themen