Dlaczego ~ True daje -2?

133

W konsoli Pythona:

~True

Daje mi:

-2

Czemu? Czy ktoś może mi wyjaśnić ten konkretny przypadek w systemie binarnym?

lukaszkups
źródło
23
ponieważ ~1jest -2, spróbuj:True == 1
Grijesh Chauhan
15
Żeby być precyzyjnym: nie jest prawdą, że " True is 1", ale to prawda True == 1.
Bach
3
Czy naprawdę myślisz, że zobaczenie UNARY_INVERT(całego kodu bajtowego) doda cokolwiek do odpowiedzi?
Wooble
2
To pytanie nie jest powtórzeniem! Pyta o określone zachowanie bool. Nie chodzi o to, jak ~działa. W rzeczywistości poprawna odpowiedź na to pytanie mogłaby w ogóle uniknąć wspominania o dopełnieniu do 2 i tym, jak ~w ogóle działa na liczbach całkowitych.
Bakuriu

Odpowiedzi:

241

int(True)jest 1.

1 jest:

00000001

i ~1jest:

11111110

Który jest -2w uzupełnieniu do dwóch 1

1 Odwróć wszystkie bity, dodaj 1 do uzyskanej liczby i zinterpretuj wynik jako binarną reprezentację wielkości i dodaj znak ujemny (ponieważ liczba zaczyna się od 1):

111111100000000100000010 
         ↑          ↑ 
       Flip       Add 1

To jest 2, ale znak jest ujemny, ponieważ MSB wynosi 1.


Warte wspomnienia:

Pomyśl o tym bool, przekonasz się, że jest to numeryczny w przyrodzie - ma dwie wartości, Truei False, i są one po prostu „dostosowane” wersje liczb całkowitych 1 i 0, że tylko drukują się inaczej. Są to podklasy typu całkowitego int.

Zachowują się więc dokładnie jak 1 i 0, z tą różnicą, że boolprzedefiniowuje stri reprwyświetla je w inny sposób.

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

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Maroun
źródło
1
@ofcapl Chciałem tylko powiedzieć: Chociaż int('1')jest to również wyjątek błędu typu, 1ale nie jest tak, ponieważ jest to podklasa @ Martijn dodała tę informację w swojej odpowiedzi. ~'1'~Trueboolint
Grijesh Chauhan
Dla przypomnienia, @ofcapl, ta odpowiedź pokazuje binarną arytmetyczną interpretację tego, co się dzieje, a nie rzeczywisty kod bajtowy (który byłby jakimś kodem pośrednim lub operacyjnym skompilowanym ze źródła).
Patrick M
5
@etrusco o jakich językach mówisz? Wiem dokładnie 0 gdzie True == -1, i znam wielu, gdzie można by powiedzieć True == 1...
l4mpi,
1
@etrusco @ l4mpi Niektóre ze starej szkoły BASIC używają -1TRUE; ma fajną właściwość, że bitowe operatory AND i OR działają również dla logicznego AND i OR ( x & -1jest różna od zera w tych samych przypadkach, która x && 1jest różna od zera w C), o ile nie obchodzi cię zwarcie . Jednak z tego co wiem, żaden mainstreamowy język nigdy nie używał określenia -1TRUE.
Quuxplusone
1
Logika formalna definiuje się truthjako bezwartościowa; ze wszystkim, czego nie truema false. Wszystkie języki programowania, które znam, falsestawiają na głowie logikę formalną, definiując ją jako bezwartościową (0) i wszystko, co nie jest fałszywym bytem true). Na przykład C # , chociaż Javascript jest czymś odstającym, mając wiele smaków prawdziwości i wiele smaków fałszu .
Nicholas Carey,
45

Typ Pythona booljest podklasą int(ze względów historycznych; wartości logiczne zostały dodane tylko w Pythonie 2.3).

Skoro int(True)jest 1, ~Trueto ~1jest -2.

Zobacz PEP 285, aby dowiedzieć się, dlaczego booljest to podklasa int.

Jeśli chcesz mieć odwrotność logiczną, użyj not:

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

Jeśli chcesz wiedzieć, dlaczego tak ~1jest -2, to dlatego, że odwracasz wszystkie bity w liczbie całkowitej ze znakiem; 00000001staje 1111110które w podpisana liczba całkowita jest liczbą ujemną, patrz uzupełnienie dwóch za :

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

gdzie początkowy 1bit oznacza, że ​​wartość jest ujemna, a pozostałe bity kodują odwrotność liczby dodatniej minus jeden.

Martijn Pieters
źródło
1
@GrijeshChauhan: Jako komplement dla dwojga możesz użyć struct.packas bin(integer)lub format(integer, '08b')nie brać pod uwagę liczb całkowitych ze znakiem .
Martijn Pieters
@thefourtheye, MartijnPieters Próbowałem, ale to jest mylące, na przykład bin(~True), bin(-2), bin(~1)wszystko daje '-0b10' Jeśli -2reprezentacja jest 10to dlaczego -znak.
Grijesh Chauhan
Co mam na myśli 102'complement to -ve?
Grijesh Chauhan
1
@GrijeshChauhan Możesz uzyskać notację uzupełniającą do dwóch liczb ujemnych i dodatnich w ten sposóbformat(-2 % (1 << 32), "032b")
thefourtheye
2
@thefourtheye: Użyłbym maski bitowej:format(-2 & ((1 << 32) - 1), "032b")
Martijn Pieters
4

~True == -2nie jest zaskakujące, jeśliTrue oznacza 1 i ~ oznacza inwersję bitową ...

... pod warunkiem, że


Edycje:

  • naprawiono mieszanie reprezentacji liczb całkowitych z operatorem inwersji bitowej
  • zastosowałem kolejne polerowanie (im krótszy przekaz, tym więcej pracy)
Wilk
źródło
2
~nie oznacza „uzupełnienia do dwóch”. ~oznacza „Bitwise Inversion”
McKay,
1
Wyrażenie „dopełnienie jedności” tak naprawdę nie odnosi się do operacji, ale odnosi się do systemu przechowywania liczb całkowitych w bitach. System, który w rzeczywistości nie jest używany w systemie komputerowym.
McKay,