Wie funktioniert der bitweise Komplementoperator (~ tilde)?

Antworten:

278

Denken Sie daran, dass negative Zahlen als Zweierkomplement des positiven Gegenstücks gespeichert werden . Als Beispiel ist hier die Darstellung von -2 im Zweierkomplement: (8 Bit)

1111 1110

Sie erhalten dies, indem Sie die binäre Darstellung einer Zahl nehmen, ihr Komplement nehmen (alle Bits invertieren) und eins hinzufügen. Zwei beginnen als 0000 0010, und durch Invertieren der Bits erhalten wir 1111 1101. Wenn Sie eins hinzufügen, erhalten Sie das obige Ergebnis. Das erste Bit ist das Vorzeichenbit, was ein Negativ impliziert.

Schauen wir uns also an, wie wir ~ 2 = -3 erhalten:

Hier sind noch einmal zwei:

0000 0010

Drehen Sie einfach alle Teile um und wir erhalten:

1111 1101

Wie sieht -3 in Zweierkomplement aus? Beginnen Sie mit positiv 3: 0000 0011, drehen Sie alle Bits auf 1111 1100 und addieren Sie eines, um den negativen Wert (-3) 1111 1101 zu erhalten.

Wenn Sie also einfach die Bits in 2 invertieren, erhalten Sie die Zweierkomplementdarstellung von -3.

Der Komplementoperator (~) FLIPPT NUR BITS. Es liegt an der Maschine, diese Bits zu interpretieren.

Anthony
quelle
43
Eine andere Sache, die vielleicht zu erwähnen ist, ist, dass der Flip als 1s-Komplement bezeichnet wird, bevor die 1 hinzugefügt wird.
Chris S
3
Es könnte anderen helfen, die sich des Komplements von Eins und des Komplements von Zwei nicht bewusst sind. Lesen Sie hier darüber. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai
1
Ist das nicht der bitweise NICHT-Operator?
Braden Best
3
Woher weiß die Maschine, dass sie eine negative Zahl mit zwei Komplementen anstelle einer höheren positiven Zahl erhält? Liegt es am Typsystem der jeweiligen Sprache, das angibt, dass der Typ ein vorzeichenbehaftetes int oder ein vorzeichenloses ist?
GL2014
@ GL2014 Ich denke du hast dort deine eigene Frage beantwortet. Nach meinem Verständnis wurde die Maschine so konzipiert, dass sie überhaupt funktioniert.
Geekidharsh
40

~ dreht die Bits im Wert um.

Warum ~2ist -3damit zu tun, wie Zahlen bitweise dargestellt werden. Zahlen werden als Zweierkomplement dargestellt .

2 ist also der Binärwert

00000010

Und ~ 2 dreht die Bits um, sodass der Wert jetzt lautet:

11111101

Welches ist die binäre Darstellung von -3.

driis
quelle
2
Ist nicht 11111101 == dezimal 253 vs -3?
AKS
10
Hängt davon ab, ob es sich um eine vorzeichenbehaftete oder vorzeichenlose Ganzzahl handelt.
Driis
18

Wie andere bereits erwähnt haben, wurden ~nur die Bits umgedreht (ändert eins zu null und null zu eins), und da das Zweierkomplement verwendet wird, erhalten Sie das Ergebnis, das Sie gesehen haben.

Eine Sache, die hinzugefügt werden muss, ist, warum das Zweierkomplement verwendet wird. Dies ist so, dass die Operationen für negative Zahlen dieselben sind wie für positive Zahlen. Stellen Sie sich -3die Zahl vor, zu der 3hinzugefügt werden sollte, um Null zu erhalten, und Sie werden sehen, dass diese Zahl ist. Denken Sie 1101daran, dass die binäre Addition genau wie die Addition der Grundschule (dezimal) ist, nur dass Sie eine tragen, wenn Sie zwei statt 10 erreichen .

 1101 +
 0011 // 3
    =
10000
    =
 0000 // lose carry bit because integers have a constant number of bits.

Daher 1101wird -3, drehen die Bits , die Sie erhalten , 0010die zwei ist.

Motti
quelle
8

Diese Operation ist eine Ergänzung, keine Negation.

Betrachten Sie ~ 0 = -1 und arbeiten Sie von dort aus.

Der Algorithmus für die Negation ist "Komplement, Inkrement".

Wusstest du? Es gibt auch "das eigene Komplement", wo die inversen Zahlen sind symmetrisch, und es hat sowohl ein 0 und eine -0.

gbarry
quelle
6

Ich weiß, dass die Antwort auf diese Frage schon lange zurückliegt, aber ich wollte meine Antwort dafür teilen.

Um das eigene Komplement einer Zahl zu finden, suchen Sie zuerst das binäre Äquivalent. Hier wird die Dezimalzahl 2wie 0000 0010in binärer Form dargestellt. Nehmen Sie nun das eigene Komplement, indem Sie alle Ziffern seiner binären Darstellung invertieren (alle Einsen in Nullen und alle Nullen in Einsen umdrehen), was zu Folgendem führt:

0000 0010 → 1111 1101

Dies ist das Einerkomplement der Dezimalzahl 2. Und da das erste Bit, dh das Vorzeichenbit, 1 in der Binärzahl ist, bedeutet dies, dass das Vorzeichen für die gespeicherte Zahl negativ ist . (hier ist die angegebene Zahl nicht 2, sondern das Komplement von 2).

Da die Zahlen nun als Zweierkomplement gespeichert sind (wobei das Einerkomplement aus einer Zahl plus Eins besteht), 1111 1101müssen wir zunächst das Zweierkomplement finden , um diese Binärzahl dezimal anzuzeigen :

1111 1101 → 0000 0010 + 1 → 0000 0011

Dies ist die Ergänzung der 2. Die Dezimaldarstellung der Binärzahl 0000 0011ist 3. Und da das Vorzeichenbit wie oben erwähnt eins war, lautet die resultierende Antwort -3.

Hinweis: Wenn Sie dieses Verfahren sorgfältig gelesen haben, hätten Sie festgestellt, dass das Ergebnis für den Komplementoperator tatsächlich die Zahl (Operand - auf den dieser Operator angewendet wird) plus eins mit negativem Vorzeichen ist. Sie können dies auch mit anderen Nummern versuchen.

Himanshu Aggarwal
quelle
Warum wird es zweimal hinzugefügt? Ich sehe add, flip, add. 0010-> 0011-> 1100->1101
Braden Best
1
Es ist Flip, Flip, Add. Erster Flip für 1's Komplement. Und da es im 2er-Komplement im System gespeichert ist, zeigt es, wenn Sie die Nummer anzeigen müssen, das 2er-Komplement der gespeicherten Nummer an (dh zweites Umdrehen und Addieren).
Himanshu Aggarwal
Aber wäre Flip (Flip (2)) nicht einfach 2? 0010 1101 0010
Braden Best
Ja, es werden nur 2 sein. Aber da, wenn die Bits im Speicher gespeichert sind, das höchstwertige Bit 1 war, wird die Zahl später negativ, wie in der obigen Antwort erläutert.
Himanshu Aggarwal
1
Nach dem, was Sie beschreiben und nach allem, was ich erforscht habe, ist dies kein Zweierkomplement, sondern ein "reguläres" Komplement oder ein bitweises NICHT. In der Logik NOT 0 = 1und NOT 1 = 0. In einem Vier-Bit-System ist NOT 0011(3) = 1100(12 ohne Vorzeichen, -4 mit Vorzeichen). Soweit ich weiß, ist das Zweierkomplement definiert als (NOT n) + 1und wird verwendet, um das negative Gegenstück einer Zahl unabhängig von der Anzahl der Bits zu finden. Also , 2c(5) = -5. Sehen Sie, jetzt macht es vollkommen Sinn. Nur solange Sie diese Operation so nennen, wie sie ist: ein bitweises NICHT.
Braden Best
4

int a = 4; System.out.println (~ a); Ergebnis wäre: -5

'~' einer beliebigen Ganzzahl in Java steht für das 1-Komplement der Nr. Zum Beispiel nehme ich ~ 4, was in der Binärdarstellung 0100 bedeutet. Erstens beträgt die Länge einer Ganzzahl vier Bytes, dh 4 * 8 (8 Bits für 1 Byte) = 32. Im Systemspeicher wird 4 also als 0000 0000 0000 0000 0000 0000 0000 0100 dargestellt. Der Operator ~ führt nun das 1er-Komplement für die obige Binär-Nr

dh 1111 1111 1111 1111 1111 1111 1111 1011-> 1-Komplement das höchstwertige Bit repräsentiert das Vorzeichen des Nein (entweder - oder +), wenn es 1 ist, dann ist das Vorzeichen '-', wenn es 0 ist, dann ist das Vorzeichen '+' gemäß Dies ist unser Ergebnis eine negative Zahl. In Java werden die negativen Zahlen in der Komplementform von 2 gespeichert. Das erfasste Ergebnis müssen wir in das Komplement von 2 umwandeln (zuerst das Komplement von 1 ausführen und nur das Komplement von 1 zu 1 addieren). Alle Einsen werden zu Nullen, mit Ausnahme des höchstwertigen Bits 1 (dies ist unsere Vorzeichendarstellung der Zahl, dh für die verbleibenden 31 Bits 1111 1111 1111 1111 1111 1111 1111 1011 (erfasstes Ergebnis des Operators ~) 1000 0000 0000 0000 0000 0000 0000 0100 (1er Komplement)

1 (2er Komplement)

1000 0000 0000 0000 0000 0000 0000 0101 jetzt ist das Ergebnis -5. Schauen Sie sich diesen Link für das Video an. <[Bitweise Operatoren in Java] https://youtu.be/w4pJ4cGWe9Y

Mike Aluydiav
quelle
2

Einfach ...........

Als Zweierkomplement einer beliebigen Zahl können wir berechnen, indem wir alle Einsen in Nullen invertieren und umgekehrt, als wir 1 hinzufügen.

Hier erzeugen N = ~ N immer Ergebnisse - (N + 1). Weil das System Daten in Form eines 2er-Komplements speichert, was bedeutet, dass es ~ N so speichert.

  ~N = -(~(~N)+1) =-(N+1). 

Beispielsweise::

  N = 10  = 1010
  Than ~N  = 0101
  so ~(~N) = 1010
  so ~(~N) +1 = 1011 

Jetzt kommt der Punkt, von dem Minus kommt. Meiner Meinung nach haben wir ein 32-Bit-Register, was bedeutet, dass 2 ^ 31 -1 Bit am Betrieb beteiligt sind, und ein Bit, das sich in früheren Berechnungen (Komplementen) ändert, als Vorzeichenbit gespeichert, das normalerweise 1 ist. Und wir erhalten das Ergebnis als ~ 10 = -11.

~ (-11) = 10;

Das obige ist wahr, wenn printf ("% d", ~ 0); wir erhalten Ergebnis: -1;

Aber printf ("% u", ~ 0) als Ergebnis: 4294967295 auf 32-Bit-Maschine.

Shubham Kumar Mishra
quelle
1

Die bitweise Komplement - Operator (~) ist eine einstellige Operator.

Es funktioniert wie folgt

Zuerst konvertiert es die angegebene Dezimalzahl in die entsprechende Binärzahl Im Fall von 2 konvertiert es zuerst 2 in 0000 0010 (in eine 8-Bit-Binärzahl).

Dann wandelt es alle 1 in der Zahl in 0 und alle Nullen in 1 um, dann wird die Zahl 1111 1101.

das ist die 2er-Komplementdarstellung von -3.

Um den vorzeichenlosen Wert mithilfe des Komplements zu finden, dh einfach 1111 1101 in eine Dezimalzahl (= 4294967293) umzuwandeln, können wir beim Drucken einfach% u verwenden.

james.bondu
quelle
1

Ich denke, für die meisten Menschen ergibt sich der Verwirrungsteil aus dem Unterschied zwischen Dezimalzahl und vorzeichenbehafteter Binärzahl. Lassen Sie uns dies zunächst klarstellen:

für die menschliche Dezimalwelt: 01 bedeutet 1, -01 bedeutet -1, für die binäre Welt des Computers: 101 bedeutet 5, wenn sie nicht vorzeichenlos ist. 101 bedeutet (-4 + 1), wenn signiert ist, während sich die signierte Ziffer an Position x befindet. | x

Das gespiegelte Bit von 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3. Die Verwirrung entsteht durch das Verwechseln des vorzeichenbehafteten Ergebnisses (101 = -3) und des nicht gesungenen Ergebnisses (101 = 5).

user7537910
quelle
1

tl; dr ~ dreht die Bits um. Infolgedessen ändert sich das Vorzeichen. ~2ist eine negative Zahl ( 0b..101). Eine negative Zahl ausgebenruby druckt -, dann Zweierkomplement ~2: -(~~2 + 1) == -(2 + 1) == 3. Positive Zahlen werden unverändert ausgegeben.

Es gibt einen internen Wert und dessen Zeichenfolgendarstellung. Bei positiven ganzen Zahlen stimmen sie grundsätzlich überein:

irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2

Letzteres entspricht:

irb(main):003:0> 2.to_s
"2"

~dreht die Bits des internen Wertes um. 2ist 0b010. ~2ist 0b..101. Zwei Punkte ( ..) repräsentieren eine unendliche Anzahl von 1's. Da das höchstwertige Bit (MSB) des Ergebnisses ist 1, ist das Ergebnis eine negative Zahl ( (~2).negative? == true). Um eine negative Zahl auszugeben , wird das Zweierkomplement des internen Werts rubygedruckt -. Das Zweierkomplement wird berechnet, indem die Bits umgedreht und dann addiert werden 1. Zweierkomplement von 0b..101ist3 . So wie:

irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3

Zusammenfassend lässt sich sagen, dass die Bits umgedreht werden, wodurch sich das Vorzeichen ändert. Um eine negative Zahl auszugeben, wird gedruckt- , dann ~~2 + 1(~~2 == 2 ).

Der Grund, warum rubynegative Zahlen so ausgegeben werden, liegt darin, dass der gespeicherte Wert als Zweierkomplement des Absolutwerts behandelt wird. Mit anderen Worten, was gespeichert ist, ist 0b..101. Es ist eine negative Zahl, und als solche ist es ein Zweierkomplement von einem gewissen Wert x. Um zu finden x, macht es zwei Komplemente von 0b..101. Welches ist das Zweierkomplement des Zweierkomplements von x. Welches ist x(z~(~2 + 1) + 1 == 2 ).

Wenn Sie ~eine negative Zahl anwenden , werden nur die Bits umgedreht (was jedoch das Vorzeichen ändert):

irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2

Was verwirrender ist, ist das ~0xffffff00 != 0xff(oder jeder andere Wert mit MSB gleich 1). Vereinfachen wir es ein wenig : ~0xf0 != 0x0f. Das liegt daran, dass es 0xf0als positive Zahl behandelt wird. Was eigentlich Sinn macht. Also , ~0xf0 == 0x..f0f. Das Ergebnis ist eine negative Zahl. Zweierkomplement von 0x..f0fist0xf1 . So:

irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"

Falls Sie keine bitweisen Operatoren auf das Ergebnis anwenden, können Sie Folgendes ~als -x - 1Operator betrachten:

irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2

Aber das nützt wohl nicht viel.

Ein Beispiel Angenommen, Sie erhalten eine 8-Bit-Netzmaske (der Einfachheit halber) und möchten die Anzahl der Netze berechnen 0. Sie können sie berechnen, indem Sie die Bits umdrehen und bit_length( 0x0f.bit_length == 4) aufrufen . Aber ~0xf0 == 0x..f0falso müssen wir die nicht benötigten Teile abschneiden:

irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4

Oder Sie können den XOR-Operator ( ^) verwenden:

irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"
x-yuri
quelle
0

Zuerst müssen wir die angegebene Ziffer in ihre Binärziffern aufteilen und sie dann umkehren, indem wir die letzte Binärziffer addieren. Nach dieser Ausführung müssen wir der vorherigen Ziffer das entgegengesetzte Vorzeichen geben, das wir als vollständig erachten ~ 2 = -3 Erklärung : 2s binäre Form ist 00000010 ändert sich zu 11111101 dies ist ein Komplement, dann ergänzt 00000010 + 1 = 00000011, was die binäre Form von drei ist und mit -sign Ie, -3

Balusabavath
quelle
0

Der bitweise Operator ist ein unärer Operator, der nach meiner Erfahrung und meinem Wissen an der Vorzeichen- und Größenmethode arbeitet.

Zum Beispiel würde ~ 2 zu -3 führen.

Dies liegt daran, dass der bitweise Operator zuerst die Zahl in Vorzeichen und Größe darstellen würde, die 0000 0010 (8-Bit-Operator) ist, wobei das MSB das Vorzeichenbit ist.

Dann würde es später die negative Zahl 2 annehmen, die -2 ist.

-2 wird in Vorzeichen und Größe als 1000 0010 (8-Bit-Operator) dargestellt.

Später wird dem LSB eine 1 hinzugefügt (1000 0010 + 1), wodurch Sie 1000 0011 erhalten.

Welches ist -3.

Santhosh Kumar Jhadav
quelle
0

Javascript Tilde (~) erzwingt einen bestimmten Wert zum eigenen Komplement - alle Bits werden invertiert. Das ist alles, was Tilde tut. Es ist kein Zeichen Meinung. Es addiert oder subtrahiert keine Menge.

0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]

Auf Standard-Desktop-Prozessoren, die Hochsprachen wie JavaScript verwenden, ist die von BASE10 signierte Arithmetik am gebräuchlichsten. Beachten Sie jedoch, dass dies nicht die einzige Art ist. Bits auf CPU-Ebene können anhand einer Reihe von Faktoren interpretiert werden. Auf der 'Code'-Ebene, in diesem Fall JavaScript, werden sie per Definition als 32-Bit-Ganzzahl mit Vorzeichen interpretiert (lassen wir Floats davon weg). Stellen Sie sich das als Quantum vor, diese 32-Bit repräsentieren viele mögliche Werte gleichzeitig. Dies hängt ganz von der Konvertierungslinse ab, durch die Sie sie betrachten.

JavaScript Tilde operation (1's complement)

BASE2 lens
~0001 -> 1110  - end result of ~ bitwise operation

BASE10 Signed lens (typical JS implementation)
~1  -> -2 

BASE10 Unsigned lens 
~1  -> 14 

Alle oben genannten sind gleichzeitig wahr.

Elvn
quelle
0

Grundsätzlich ist Aktion eine Ergänzung, keine Negation.

Hier erzeugen x = ~ x immer Ergebnisse - (x + 1).

x = ~ 2

- (2 + 1)

-3

Sunil
quelle