Warum ergibt ~ True -2?

132

In der Python-Konsole:

~True

Gibt mir:

-2

Warum? Kann mir jemand diesen speziellen Fall binär erklären?

lukaszkups
quelle
22
weil ~1ist -2, versuchen Sie:True == 1
Grijesh Chauhan
15
Um genau zu sein: Es ist nicht wahr, dass " True is 1", aber es ist wahr, dass True == 1.
Bach
3
Glauben Sie wirklich, dass das Sehen UNARY_INVERT(der gesamte Bytecode) den Antworten etwas hinzufügen wird?
Wooble
2
Diese Frage ist kein Duplikat! Es fragt nach einem bestimmten Verhalten von bool. Es geht nicht darum, wie es ~funktioniert. Tatsächlich könnte eine gültige Antwort auf diese Frage vermeiden, das Komplement von 2 und die Funktionsweise ~von ganzen Zahlen überhaupt zu erwähnen .
Bakuriu

Antworten:

240

int(True)ist 1.

1 ist:

00000001

und ~1ist:

11111110

Welches ist -2in Two's Komplement 1

1 Drehen Sie alle Bits um, addieren Sie 1 zur resultierenden Zahl und interpretieren Sie das Ergebnis als binäre Darstellung der Größe und fügen Sie ein negatives Vorzeichen hinzu (da die Zahl mit 1 beginnt):

11111110  00000001  00000010 
                    
       Flip       Add 1

Welches ist 2, aber das Vorzeichen ist negativ, da das MSB 1 ist.


Erwähnenswert:

Denken boolSie daran, Sie werden feststellen, dass es numerischer Natur ist - Es hat zwei Werte, Trueund Falsees handelt sich lediglich um "angepasste" Versionen der Ganzzahlen 1 und 0, die sich nur unterschiedlich drucken. Sie sind Unterklassen vom Typ Integer int.

Sie verhalten sich also genau wie 1 und 0, außer dass sie boolneu definiert strund reprunterschiedlich angezeigt werden.

>>> type(True)
<class 'bool'>
>>> isinstance(True, int)
True

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Maroun
quelle
1
@ofcapl nur sagen wollte: Obwohl int('1')auch ist 1aber ~'1'eine Typeerror - Ausnahme sein , während ~Truenicht das ist , weil booles eine Unterklasse von int@ Martijn diese Informationen in seiner Antwort gegeben.
Grijesh Chauhan
Für den Datensatz @ofcapl zeigt diese Antwort die binäre arithmetische Interpretation dessen, was vor sich geht, nicht den tatsächlichen Bytecode (der eine Art Zwischen- oder Betriebsebenencode wäre, der aus der Quelle kompiliert wurde).
Patrick M
5
@etrusco über welche Sprachen sprichst du? Ich weiß genau 0 wo True == -1, und ich kenne viele wo man das sagen könnte True == 1...
l4mpi
1
@etrusco @ l4mpi Einige BASICs der alten Schule verwenden -1für TRUE. Es hat die nette Eigenschaft, dass die bitweisen UND- und ODER-Operatoren auch für logisches UND und ODER funktionieren ( x & -1in den gleichen Fällen x && 1ungleich Null wie in C ungleich Null), solange Sie sich nicht für Kurzschlüsse interessieren . Soweit ich weiß, hat jedoch noch nie eine Mainstream-Sprache -1für TRUE verwendet.
Quuxplusone
1
Formale Logik definiert truthals univaliert; mit allem was nicht trueist false. Alle Programmiersprachen, die mir bekannt sind, stellen die formale Logik auf den Kopf und definieren sie falseals univaliert (0) und alles, was nicht falsch ist true. Zum Beispiel C # , obwohl Javascript so etwas wie ein Ausreißer ist und mehrere Arten von Wahrhaftigkeit und mehrere Arten von Falschheit aufweist .
Nicholas Carey
45

Der Python- boolTyp ist eine Unterklasse von int(aus historischen Gründen; Boolesche Werte wurden nur in Python 2.3 hinzugefügt).

Da int(True)ist 1, ~Trueist ~1ist -2.

In PEP 285 erfahren Sie, warum booles sich um eine Unterklasse von handelt int.

Wenn Sie die boolesche Umkehrung wünschen, verwenden Sie not:

>>> not True
False
>>> not False
True

Wenn Sie wissen möchten, warum dies so ~1ist -2, liegt dies daran, dass Sie alle Bits in einer vorzeichenbehafteten Ganzzahl invertieren. 00000001wird, 1111110was in einer vorzeichenbehafteten Ganzzahl eine negative Zahl ist, siehe Zweierkomplement :

>>> # Python 3
...
>>> import struct
>>> format(struct.pack('b', 1)[0], '08b')
'00000001'
>>> format(struct.pack('b', ~1)[0], '08b')
'11111110'

Dabei bedeutet das Anfangsbit, 1dass der Wert negativ ist, und der Rest der Bits codiert die Umkehrung der positiven Zahl minus eins.

Martijn Pieters
quelle
1
@GrijeshChauhan: Für zwei Kompliment, könnten Sie verwenden struct.pack, wie bin(integer)oder format(integer, '08b')nehmen Sie nicht unterzeichnet ganzen Zahlen berücksichtigt.
Martijn Pieters
@thefourtheye, MartijnPieters ich versucht , aber es ist verwirrend , zum Beispiel bin(~True), bin(-2), bin(~1)gibt all '-0b10' Wenn -2Darstellung ist 10dann , warum -Zeichen.
Grijesh Chauhan
Was meine 10ich dann selbst als Komplement?
Grijesh Chauhan
1
@GrijeshChauhan Sie können die Komplementnotation der beiden sowohl negativer als auch positiver Zahlen wie diese erhaltenformat(-2 % (1 << 32), "032b")
thefourtheye
2
@thefourtheye: Ich würde eine Bitmaske verwenden:format(-2 & ((1 << 32) - 1), "032b")
Martijn Pieters
4

~True == -2ist nicht überraschend, wenn True Mittel 1 und ~ Mittel bitweise Inversion bedeuten ...

... vorausgesetzt das


Bearbeitungen:

  • Die Mischung zwischen ganzzahliger Darstellung und bitweiser Inversionsoperator wurde korrigiert
  • ein weiteres Polieren angewendet (je kürzer die Nachricht, desto mehr Arbeit erforderlich)
Wolf
quelle
2
~bedeutet nicht "2s Komplement". ~bedeutet "Bitweise Inversion"
McKay
1
Der Ausdruck "Ein Komplement" bezieht sich nicht wirklich auf eine Operation, sondern auf ein System zum Speichern von ganzen Zahlen in Bits. Ein System, das in einem Computersystem nicht verwendet wird.
McKay