Por que ~ True resulta em -2?

132

No console do Python:

~True

Dá-me:

-2

Por quê? Alguém pode me explicar esse caso em particular em binário?

lukaszkups
fonte
22
porque ~1é -2, tente:True == 1
Grijesh Chauhan 19/02
15
Só para ser mais preciso: não é verdade que " True is 1", mas é verdade isso True == 1.
Bach
3
Você realmente acha que ver UNARY_INVERT(todo o bytecode) adicionará algo às respostas?
Wooble
2
Esta pergunta não é uma duplicata! Ele pergunta sobre um comportamento específico de bool. Não é sobre como ~funciona. De fato, uma resposta válida para essa pergunta pode evitar mencionar o complemento de 2 e como ~funciona em números inteiros.
Bakuriu

Respostas:

240

int(True)é 1.

1 é:

00000001

e ~1é:

11111110

Que está -2no complemento do Two 1

1 Gire todos os bits, adicione 1 ao número resultante e interprete o resultado como uma representação binária da magnitude e adicione um sinal negativo (já que o número começa com 1):

11111110  00000001  00000010 
                    
       Flip       Add 1

Qual é 2, mas o sinal é negativo, pois o MSB é 1.


Vale a pena mencionar:

Pense bool, você descobrirá que é de natureza numérica - tem dois valores TrueeFalse , e eles são apenas versões "personalizadas" dos números inteiros 1 e 0 que somente se imprimem de maneira diferente. Eles são subclasses do tipo inteiro int.

Portanto, eles se comportam exatamente como 1 e 0, exceto que boolredefine stre reprpara exibi-los de maneira diferente.

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

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Maroun
fonte
1
@ofcapl Só queria dizer: Embora int('1')também é 1, mas ~'1'ser uma exceção TypeError enquanto ~Truenão é isso é porque boolé uma subclasse de int@ Martijn adicionou esta informação na sua resposta.
Grijesh Chauhan
Para o registro, @ofcapl, esta resposta mostra a interpretação aritmética binária do que está acontecendo, não o bytecode real (que seria algum tipo de código de nível intermediário ou de operação compilado a partir da fonte).
Patrick M
5
@etrusco de que idiomas você está falando? Eu sei exatamente onde 0 True == -1, e sei que muitos que se poderia dizer que True == 1...
l4mpi
1
@etrusco @ l4mpi Alguns BASIC da velha escola usam -1para VERDADEIRO; ele tem a propriedade legal de que os operadores AND e OR bit a bit também trabalham para AND e OR lógicos ( x & -1é diferente de zero nos mesmos casos que x && 1é diferente de zero em C), desde que você não se preocupe com curtos-circuitos . No entanto, até onde eu sei, nenhum idioma convencional já usou o -1TRUE.
Quuxplusone
1
Lógica formal define truthcomo desvalorizada; com tudo o que não está truesendo false. Todas as linguagens de programação que eu conheço mudam de lógica formal, definindo falsecomo desvalorizado (0) e tudo o que não é falso true). Por exemplo, C # , embora o Javascript seja um pouco estranho, com vários sabores de veracidade e vários sabores de falsidade .
Nicholas Carey
45

O booltipo Python é uma subclasse deint (por razões históricas; os booleanos foram adicionados apenas no Python 2.3).

Desde que int(True)é 1, ~Trueé ~1é-2 .

Veja PEP 285 para saber por que booluma subclasse de int.

Se você queria o inverso booleano, use not:

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

Se você queria saber por que ~1é -2, é porque você está invertendo todos os bits em um inteiro assinado; 00000001torna-se 1111110que em um número inteiro assinado é um número negativo, consulte o complemento de dois :

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

onde o 1bit inicial significa que o valor é negativo e o restante dos bits codifica o inverso do número positivo menos um.

Martijn Pieters
fonte
1
@GrijeshChauhan: Para complemento de dois, você poderia usar struct.pack, como bin(integer)ou format(integer, '08b')não tomar inteiros assinados em conta.
Martijn Pieters
@ thefourtheye, MartijnPieters Eu tentei Mas é confuso bin(~True), por exemplo bin(-2), bin(~1)tudo dá '-0b10' Se -2representação é 10então por que -assinar.
Grijesh Chauhan
O que eu quero dizer com 102'complemento então -ve?
Grijesh Chauhan
1
@GrijeshChauhan Você pode obter a notação complementar de dois de números negativos e positivos como esteformat(-2 % (1 << 32), "032b")
thefourtheye
2
@thefourtheye: Eu usaria uma máscara de bits:format(-2 & ((1 << 32) - 1), "032b")
Martijn Pieters
4

~True == -2não é surpreendente seTrue meios 1 e ~ meios inversão bit a bit ...

... desde que

  • True pode ser tratado como um número inteiro e
  • números inteiros são representados no complemento de Two

Editar% s:

  • Corrigida a mistura entre representação inteira e operador de inversão bit a bit
  • aplicou outro polimento (quanto menor a mensagem, mais trabalho é necessário)
Lobo
fonte
2
~não significa "complemento 2s". ~significa "Inversão por bits"
McKay
1
A frase "complemento de um" não se refere realmente a uma operação, tanto quanto a um sistema de armazenamento de números inteiros em bits. Um sistema que não é realmente usado em um sistema de computador.
22414 McKay