Pourquoi ~ True donne-t-il -2?

132

Dans la console Python:

~True

Donne moi:

-2

Pourquoi? Quelqu'un peut-il m'expliquer ce cas particulier en binaire?

lukaszkups
la source
22
parce que ~1c'est -2, essayez:True == 1
Grijesh Chauhan
15
Juste pour être précis: ce n'est pas vrai que " True is 1", mais c'est vrai que True == 1.
Bach
3
Pensez-vous vraiment que voir UNARY_INVERT(l'ensemble du bytecode) ajoutera quelque chose aux réponses?
Wooble
2
Cette question n'est pas un doublon! Il pose des questions sur un comportement spécifique de bool. Il ne s'agit pas de savoir comment ~fonctionne. En fait, une réponse valable à cette question pourrait éviter de mentionner le complément de 2 et comment ~fonctionne sur les entiers.
Bakuriu

Réponses:

240

int(True)est 1.

1 est:

00000001

et ~1est:

11111110

Qui est -2dans le complément à deux 1

1 Retournez tous les bits, ajoutez 1 au nombre résultant et interprétez le résultat comme une représentation binaire de la grandeur et ajoutez un signe négatif (puisque le nombre commence par 1):

11111110  00000001  00000010 
                    
       Flip       Add 1

Qui est 2, mais le signe est négatif puisque le MSB est 1.


À noter:

Pensez-y bool, vous constaterez qu'il est de nature numérique - Il a deux valeurs Trueet False, et ce ne sont que des versions "personnalisées" des entiers 1 et 0 qui ne s'impriment différemment. Ce sont des sous - classes de type entier int.

Donc ils se comportent exactement comme 1 et 0, sauf que cela boolredéfinit stret reprde les afficher différemment.

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

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Maroun
la source
1
@ofcapl Je voulais juste dire: Bien int('1')est aussi , 1mais ~'1'une exception TypeError alors ~Trueest - ce pas parce que boolest une sous - classe de int@ Martijn a ajouté cette information dans sa réponse.
Grijesh Chauhan
Pour mémoire, @ofcapl, cette réponse montre l'interprétation arithmétique binaire de ce qui se passe, pas le bytecode réel (qui serait une sorte de code de niveau intermédiaire ou opérationnel compilé à partir de la source).
Patrick M
5
@etrusco de quelles langues parlez-vous? Je sais exactement 0 où True == -1, et j'en connais beaucoup où l'on pourrait dire ça True == 1...
l4mpi
1
@etrusco @ l4mpi Certains BASIC de la vieille école utilisent -1pour TRUE; il a la belle propriété que les opérateurs binaires AND et OR fonctionnent également pour les ET et OU logiques ( x & -1est non nul dans les mêmes cas que x && 1non nul en C), tant que vous ne vous souciez pas du court-circuit . Cependant, pour autant que je sache, aucun langage courant n'a jamais utilisé -1VRAI.
Quuxplusone
1
La logique formelle se définit truthcomme sans valeur; avec tout ce qui est pas trueêtre false. Tous les langages de programmation dont je suis conscient tournent la logique formelle sur sa tête, définissant falsecomme non valorisé (0) et tout ce qui n'est pas un être faux true). Par exemple, C # , bien que Javascript soit quelque peu aberrant, ayant plusieurs saveurs de vérité et plusieurs saveurs de fausseté .
Nicholas Carey
45

Le booltype Python est une sous-classe de int(pour des raisons historiques; les booléens n'ont été ajoutés que dans Python 2.3).

Depuis int(True)est 1, ~Trueest ~1est -2.

Voir PEP 285 pour savoir pourquoi boolest une sous-classe de int.

Si vous vouliez l'inverse booléen, utilisez not:

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

Si vous voulez savoir pourquoi ~1est -2, il est parce que vous êtes tous les bits dans inverseuses un entier signé; 00000001devient 1111110qui dans un entier signé est un nombre négatif, voir Complément à deux :

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

où le 1bit initial signifie que la valeur est négative, et le reste des bits codent l'inverse du nombre positif moins un.

Martijn Pieters
la source
1
@GrijeshChauhan: Pour le compliment à deux, vous pouvez utiliser struct.pack, comme bin(integer)ou format(integer, '08b')ne pas prendre en compte les entiers signés.
Martijn Pieters
@thefourtheye, MartijnPieters I Tried Mais il est source de confusion , par exemple bin(~True), bin(-2), bin(~1)tout donne '-0b10' Si la -2représentation est 10alors pourquoi -signe.
Grijesh Chauhan
Qu'est-ce que je veux dire par 10lui - même 2'complement alors -ve?
Grijesh Chauhan
1
@GrijeshChauhan Vous pouvez obtenir la notation du complément à deux des nombres négatifs et positifs comme ceciformat(-2 % (1 << 32), "032b")
thefourtheye
2
@thefourtheye: J'utiliserais un bitmask:format(-2 & ((1 << 32) - 1), "032b")
Martijn Pieters
4

~True == -2n'est pas surprenant si True signifie 1 et ~ signifie l' inversion au niveau du bit ...

... à condition que

  • True peut être traité comme un entier et
  • les entiers sont représentés dans le complément à deux

Modifications:

  • correction du mélange entre la représentation entière et l'opérateur d'inversion au niveau du bit
  • appliqué un autre polissage (plus le message est court, plus il faut de travail)
Loup
la source
2
~ne signifie pas "complément 2s". ~signifie "Bitwise Inversion"
McKay
1
L'expression «Complément à un» ne fait pas vraiment référence à une opération, autant qu'elle se réfère à un système de stockage d'entiers en bits. Un système qui n'est pas réellement utilisé dans un système informatique.
McKay