Was sind bitweise Operatoren?


129

Ich bin jemand, der Code nur zum Spaß schreibt und sich weder in einer akademischen noch in einer professionellen Umgebung wirklich damit beschäftigt hat. Dinge wie diese bitweisen Operatoren entgehen mir also wirklich.

Ich habe einen Artikel über JavaScript gelesen, der anscheinend bitweise Operationen unterstützt. Ich sehe diese Operation immer wieder an einigen Stellen erwähnt, und ich habe versucht zu lesen, um herauszufinden, was genau es ist, aber ich scheine es überhaupt nicht zu verstehen. Also was sind sie? Klare Beispiele wären toll! : D.

Nur noch ein paar Fragen - was sind einige praktische Anwendungen von bitweisen Operationen? Wann könnten Sie sie verwenden?


2
Bei weiteren Fragen möchten Sie möglicherweise eine neue SO-Frage hinzufügen und auf diese verweisen. Auf diese Weise erhalten Sie wahrscheinlich bessere Antworten.
Greg Hewgill

Antworten:


186

Da niemand das Thema angesprochen hat, warum diese nützlich sind:

Ich benutze oft bitweise Operationen, wenn ich mit Flags arbeite. Wenn Sie beispielsweise eine Reihe von Flags an eine Operation übergeben möchten (z. B. wenn File.Open()sowohl der Lesemodus als auch der Schreibmodus aktiviert sind), können Sie sie als einzelnen Wert übergeben. Dies wird erreicht, indem jedem möglichen Flag ein eigenes Bit in einem Bitset zugewiesen wird (Byte, Short, Int oder Long). Beispielsweise:

 Read: 00000001
Write: 00000010

Wenn Sie also Lesen UND Schreiben übergeben möchten, übergeben Sie (READ | WRITE), in dem die beiden kombiniert werden

00000011

Was dann am anderen Ende entschlüsselt werden kann wie:

if ((flag & Read) != 0) { //...

welche prüft

00000011 &
00000001

was zurückkehrt

00000001

Dies ist nicht 0, daher gibt das Flag READ an.

Sie können XOR verwenden, um verschiedene Bits umzuschalten. Ich habe dies verwendet, wenn ich ein Flag zum Festlegen von Richtungseingaben (Auf, Ab, Links, Rechts) verwendet habe. Zum Beispiel, wenn sich ein Sprite horizontal bewegt und ich möchte, dass es sich umdreht:

     Up: 00000001
   Down: 00000010
   Left: 00000100
  Right: 00001000
Current: 00000100

Ich XOR einfach den aktuellen Wert mit (LINKS | RECHTS), wodurch in diesem Fall LINKS aus und RECHTS eingeschaltet wird.

Bitverschiebung ist in mehreren Fällen nützlich.

x << y

ist das gleiche wie

x * 2 y

Wenn Sie schnell mit einer Zweierpotenz multiplizieren müssen, aber darauf achten müssen, dass ein 1-Bit in das obere Bit verschoben wird, wird die Zahl negativ, es sei denn, sie ist ohne Vorzeichen. Dies ist auch nützlich, wenn Sie mit unterschiedlichen Datengrößen arbeiten. Beispiel: Lesen einer Ganzzahl aus vier Bytes:

int val = (A << 24) | (B << 16) | (C << 8) | D;

Angenommen, A ist das höchstwertige Byte und D das niedrigste. Es würde enden als:

A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011

Farben werden häufig auf diese Weise gespeichert (wobei das höchstwertige Byte entweder ignoriert oder als Alpha verwendet wird):

A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000

Um die Werte wieder zu finden, verschieben Sie einfach die Bits nach rechts, bis sie unten sind, und maskieren Sie dann die verbleibenden Bits höherer Ordnung:

Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF

0xFFist das gleiche wie 11111111. Für Red würden Sie also im Wesentlichen Folgendes tun:

Color >> 16 = (filled in 00000000 00000000)11111111 00010101  (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)

x << n, also muss n die Form 2 ^ haben?
Ahmed C

28

Es ist anzumerken, dass die als andere Antworten aufgelisteten Einzelbit-Wahrheitstabellen jeweils nur mit einem oder zwei Eingabebits funktionieren. Was passiert, wenn Sie Ganzzahlen verwenden, z.

int x = 5 & 6;

Die Antwort liegt in der binären Erweiterung jedes Eingangs:

  5 = 0 0 0 0 0 1 0 1
& 6 = 0 0 0 0 0 1 1 0
---------------------
      0 0 0 0 0 1 0 0

Jedes Bitpaar in jeder Spalte wird durch die "UND" -Funktion geführt, um das entsprechende Ausgangsbit in der unteren Zeile zu erhalten. Die Antwort auf den obigen Ausdruck lautet also 4. Die CPU hat (in diesem Beispiel) 8 separate "UND" -Operationen parallel ausgeführt, eine für jede Spalte.

Ich erwähne das, weil ich mich noch daran erinnere, dieses "AHA!" Moment, als ich vor vielen Jahren davon erfuhr.


Wow, das macht jetzt viel mehr Sinn. Es klang viel komplizierter als es anscheinend ist. Vielen Dank. Ich bin mir nicht sicher, welche ich als die richtige Antwort wählen soll, da es viele gute gibt, und ich kann das nicht verbessern. Danke
klicken Sie auf den

27

Bitweise Operatoren sind Operatoren, die jeweils ein Bit bearbeiten.

UND ist nur dann 1, wenn beide Eingänge 1 sind.

ODER ist 1, wenn einer oder mehrere seiner Eingänge 1 sind.

XOR ist nur dann 1, wenn genau einer seiner Eingänge 1 ist.

NOT ist nur dann 1, wenn seine Eingabe 0 ist.

Diese können am besten als Wahrheitstabellen beschrieben 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 beiden Eingänge angezeigt werden.

AND|0 1      OR|0 1
---+----    ---+----
  0|0 0       0|0 1
  1|0 1       1|1 1

XOR|0 1     NOT|0 1
---+----    ---+---
  0|0 1        |1 0
  1|1 0

Ein Beispiel ist, wenn Sie nur die unteren 4 Bits einer ganzen Zahl wollen, Sie UND es mit 15 (binär 1111) also:

    203: 1100 1011
AND  15: 0000 1111
------------------
 IS  11: 0000 1011

16

Dies sind die bitweisen Operatoren, die alle in JavaScript unterstützt werden:

  • op1 & op2- Der ANDOperator vergleicht zwei Bits und generiert ein Ergebnis von 1, wenn beide Bits 1 sind. Andernfalls wird 0 zurückgegeben.

  • op1 | op2- Der OROperator vergleicht zwei Bits und generiert ein Ergebnis von 1, wenn die Bits komplementär sind. Andernfalls wird 0 zurückgegeben.

  • op1 ^ op2- Der EXCLUSIVE-OROperator vergleicht zwei Bits und gibt 1 zurück, wenn eines der Bits 1 ist, und gibt 0, wenn beide Bits 0 oder 1 sind.

  • ~op1- Mit dem COMPLEMENTOperator werden alle Bits des Operanden invertiert.

  • op1 << op2- Der SHIFT LEFTOperator verschiebt die Bits nach links, verwirft das Bit ganz links und weist dem Bit ganz rechts den Wert 0 zu. Bei jeder Bewegung nach links wird op1 effektiv mit 2 multipliziert.

  • op1 >> op2- Der SHIFT RIGHTOperator verschiebt die Bits nach rechts, verwirft das Bit ganz rechts und weist dem Bit ganz links den Wert 0 zu. Jede Bewegung nach rechts teilt op1 effektiv in zwei Hälften. Das am weitesten links stehende Vorzeichenbit bleibt erhalten.

  • op1 >>> op2- Der Operator SHIFT RIGHT- ZERO FILLverschiebt die Bits nach rechts, verwirft das Bit ganz rechts und weist dem Bit ganz links den Wert 0 zu. Jede Bewegung nach rechts teilt op1 effektiv in zwei Hälften. Das am weitesten links stehende Vorzeichenbit wird verworfen.


"wenn die Bits komplementär sind" - waht?
Andrey Tyukin

@AndreyTyukin zwei Bits sind komplementär, wenn eines von ihnen 1 und das andere 0 ist.
Jeff Hillman

@ JeffHillman Gemäß Ihrer Beschreibung im Kommentar sind 1 und 1 nicht "komplementär". Dann ist mir unklar, warum 1 | 1gibt 1und nicht 0, und wie |soll sich dann unterscheiden von ^. Ich musste dieses Q / A vor einigen Tagen als doppeltes Ziel verwenden und wünschte mir, dass man nach 10 Jahren ein klareres kanonisches Duplikat für diese Art von Fragen haben würde.
Andrey Tyukin

4

Um es ein bisschen mehr aufzuschlüsseln, hat es viel mit der binären Darstellung des fraglichen Wertes zu tun.

Zum Beispiel (dezimal):
x = 8
y = 1

würde herauskommen zu (in binär):
x = 1000
y = 0001

Von dort aus können Sie Rechenoperationen wie 'und' oder 'oder' ausführen. in diesem Fall:
x | y =
1000 
0001 |
------ ------.
1001

oder ... 9 in Dezimalzahl

Hoffe das hilft.


|ist eine OP-Operation?
Si8

Aus irgendeinem Grund machte das für mich am meisten Sinn. Immer noch nicht sicher über den x | y = 1000 0001 |Teil
Samayo

4

Wenn der Begriff "bitweise" erwähnt wird, wird manchmal klargestellt, dass es sich nicht um einen "logischen" Operator handelt.

In JavaScript behandeln bitweise Operatoren ihre Operanden beispielsweise als eine Folge von 32 Bits (Nullen und Einsen) . In der Zwischenzeit werden logische Operatoren normalerweise mit booleschen (logischen) Werten verwendet , können jedoch mit nicht-booleschen Typen arbeiten.

Nehmen Sie zum Beispiel expr1 && expr2.

Gibt expr1 zurück, wenn es in false konvertiert werden kann. Andernfalls wird expr2 zurückgegeben. Bei Verwendung mit Booleschen Werten gibt && also true zurück, wenn beide Operanden true sind. Andernfalls wird false zurückgegeben.

a = "Cat" && "Dog"     // t && t returns Dog
a = 2 && 4     // t && t returns 4

Wie andere angemerkt haben, ist 2 & 4 ein bitweises UND, daher wird 0 zurückgegeben.

Sie können Folgendes in test.html oder etwas anderes kopieren und testen:

<html>
<body>
<script>
    alert("\"Cat\" && \"Dog\" = " + ("Cat" && "Dog") + "\n"
        + "2 && 4 = " + (2 && 4) + "\n"
        + "2 & 4 = " + (2 & 4));
</script>

3

Bei der digitalen Computerprogrammierung arbeitet eine bitweise Operation mit einem oder mehreren Bitmustern oder Binärzahlen auf der Ebene ihrer einzelnen Bits. Es ist eine schnelle, primitive Aktion, die direkt vom Prozessor unterstützt wird und zum Bearbeiten von Werten für Vergleiche und Berechnungen verwendet wird.

Operationen :

  • bitweise UND

  • bitweise ODER

  • bitweise NICHT

  • bitweises XOR

  • etc

Listenpunkt

    AND|0 1        OR|0 1 
    ---+----      ---+---- 
      0|0 0         0|0 1 
      1|0 1         1|1 1 

   XOR|0 1        NOT|0 1 
   ---+----       ---+--- 
     0|0 1           |1 0 
     1|1 0

Z.B.

    203: 1100 1011
AND  15: 0000 1111
------------------
  =  11: 0000 1011

Verwendung des bitweisen Operators

  • Die Linksverschiebungs- und Rechtsverschiebungsoperatoren entsprechen der Multiplikation bzw. Division durch x * 2 y .

Z.B.

int main()
{
     int x = 19;
     printf ("x << 1 = %d\n" , x <<1);
     printf ("x >> 1 = %d\n", x >>1);
     return 0;
}
// Output: 38 9
  • Mit dem Operator & kann schnell überprüft werden, ob eine Zahl ungerade oder gerade ist

Z.B.

int main()
{
    int x = 19;
    (x & 1)? printf("Odd"): printf("Even");
    return 0;
 }
// Output: Odd
  • Schnelles Finden von mindestens x und y ohne if elseAnweisung

Z.B.

int min(int x, int y)
{
    return y ^ ((x ^ y) & - (x < y))
}
  • Umwandlung von Dezimal in Binär

Z.B.

#include <stdio.h>
int main ()
{
    int n , c , k ;
    printf("Enter an integer in decimal number system\n " ) ;
    scanf( "%d" , & n );
    printf("%d in binary number
    system is: \n " , n ) ;
    for ( c = 31; c >= 0 ; c -- )
    {
         k = n >> c ;
         if ( k & 1 )
              printf("1" ) ;
         else
              printf("0" ) ;
      }
      printf(" \n " );
      return 0 ;
}
  • Die XOR-Gate-Verschlüsselung ist aufgrund ihrer Vollständigkeit und erneuten Verwendung durch den Programmierer eine beliebte Technik.
  • Der bitweise XOR-Operator ist aus Sicht der technischen Interviews der nützlichste Operator.

Das bitweise Verschieben funktioniert nur mit + ve Nummer

Es gibt auch einen weiten Anwendungsbereich der bitweisen Logik


"Komplixblität und Reare ..."?
Jonathan Cross

The left-shift and right-shift operators are equivalent to multiplication and division by x * 2y respectively.Das stimmt! muyiy.cn/question/program/102.html
xgqfrms


1

Es könnte hilfreich sein, so darüber nachzudenken. So funktioniert AND (&):

Grundsätzlich heißt es, dass beide Zahlen eins sind. Wenn Sie also zwei Zahlen 5 und 3 haben, werden sie in Binärzahlen umgewandelt und der Computer denkt nach

         5: 00000101
         3: 00000011

sind beide eins: 00000001 0 ist falsch, 1 ist wahr

Das UND von 5 und 3 ist also eins. Der Operator OR (|) macht dasselbe, außer dass nur eine der Zahlen eins sein muss, um 1 auszugeben, nicht beide.


-5

Ich hörte immer wieder, wie langsam bitweise JavaScript-Operatoren waren. Ich habe einige Tests für meinen neuesten Blog-Beitrag durchgeführt und festgestellt, dass sie in mehreren Tests 40% bis 80% schneller waren als die arithmetische Alternative. Vielleicht waren sie früher langsam. In modernen Browsern liebe ich sie.

Ich habe einen Fall in meinem Code, der dadurch schneller und einfacher zu lesen ist. Ich werde meine Augen offen halten für mehr.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.