¿Por qué ~ True da como resultado -2?

132

En la consola de Python:

~True

Me da

-2

¿Por qué? ¿Alguien puede explicarme este caso particular en binario?

lukaszkups
fuente
22
porque ~1es -2, intente:True == 1
Grijesh Chauhan
15
Para ser precisos: no es cierto eso " True is 1", pero es cierto eso True == 1.
Bach
3
¿Realmente crees que ver UNARY_INVERT(todo el código de bytes) agregará algo a las respuestas?
Wooble
2
¡Esta pregunta no es un duplicado! Pregunta sobre un comportamiento específico de bool. No se trata de cómo ~funciona. De hecho, una respuesta válida a esta pregunta podría evitar mencionar el complemento de 2 y cómo ~funciona en los enteros.
Bakuriu

Respuestas:

240

int(True)es 1.

1 es:

00000001

y ~1es:

11111110

Que está -2en el complemento 1 de Two

1 Voltee todos los bits, agregue 1 al número resultante e interprete el resultado como una representación binaria de la magnitud y agregue un signo negativo (ya que el número comienza con 1):

11111110  00000001  00000010 
                    
       Flip       Add 1

Que es 2, pero el signo es negativo ya que el MSB es 1.


Vale la pena mencionar:

Piense acerca de bool, usted encontrará que es numérico en la naturaleza - Tiene dos valores, Truey False, y son simplemente versiones de los números enteros 1 y 0 que sólo se imprimen de forma diferente "a medida". Son subclases del tipo entero int.

Entonces se comportan exactamente como 1 y 0, excepto que los boolredefine stry los reprmuestra de manera diferente.

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

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Maroun
fuente
1
@ofcapl Sólo quería decir: Aunque int('1')también es 1sino ~'1'ser una excepción TypeError mientras que ~Trueno es esto se debe a que booles una subclase de int@ Martijn añadió esta información en su respuesta.
Grijesh Chauhan
Para el registro, @ofcapl, esta respuesta muestra la interpretación aritmética binaria de lo que está pasando, no el actual código de bytes (que sería algún tipo de código intermedio o nivel de operación compilado a partir de la fuente).
Patrick M
55
@etrusco ¿de qué idiomas estás hablando? Sé exactamente 0 dónde True == -1, y sé muchos dónde se podría decir que True == 1...
l4mpi
1
@etrusco @ l4mpi Algunos BASIC de la vieja escuela usan -1para VERDADERO; tiene la buena propiedad de que los operadores AND y OR a nivel de bits también funcionan para AND y OR lógicos ( x & -1no es cero en los mismos casos que x && 1no es cero en C), siempre y cuando no le importe el cortocircuito . Sin embargo, hasta donde yo sé, ningún lenguaje convencional se ha utilizado -1para VERDADERO.
Quuxplusone
1
La lógica formal se define truthcomo no valorada; con todo lo que no es trueser false. Todos los lenguajes de programación que conozco se vuelven lógicos formales, definiéndolos falsecomo no valorados (0) y todo eso no es ser falso true). Por ejemplo, C # , aunque Javascript es algo atípico, tiene múltiples sabores de veracidad y múltiples sabores de falsedad .
Nicholas Carey
45

El booltipo Python es una subclase de int(por razones históricas; los booleanos solo se agregaron en Python 2.3).

Como int(True)es 1, ~Truees ~1es -2.

Ver PEP 285 para saber por qué booles una subclase de int.

Si quería el inverso booleano, use not :

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

Si quería saber por qué ~1es así -2, es porque está invirtiendo todos los bits en un entero con signo; 00000001se convierte en 1111110el cual en una firmado entero es un número negativo, ver el complemento a dos :

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

donde el 1bit inicial significa que el valor es negativo, y el resto de los bits codifican el inverso del número positivo menos uno.

Martijn Pieters
fuente
1
@GrijeshChauhan: Para el cumplido de dos, puedes usar struct.pack, como bin(integer)o format(integer, '08b')no tener en cuenta enteros firmados.
Martijn Pieters
@thefourtheye, MartijnPieters Probé Pero es confuso bin(~True), por ejemplo bin(-2), bin(~1)todo da '-0b10' Si la -2representación es 10entonces por qué -firmar.
Grijesh Chauhan
¿A qué me refiero 10con 2'complemento entonces -ve?
Grijesh Chauhan
1
@GrijeshChauhan Puede obtener la notación complementaria de los dos números negativos y positivos como esteformat(-2 % (1 << 32), "032b")
cuarto de
2
@thefourtheye: Usaría una máscara de bits:format(-2 & ((1 << 32) - 1), "032b")
Martijn Pieters
4

~True == -2se no es sorprendente si True los medios 1 y los ~ medios bit a bit de inversión ...

... siempre que


Ediciones:

  • Se corrigió la mezcla entre la representación de enteros y el operador de inversión bit a bit
  • aplicado otro pulido (cuanto más corto es el mensaje, más trabajo se necesita)
Lobo
fuente
2
~no significa "complemento 2s". ~significa "Inversión a nivel de bits"
McKay
1
La frase "complemento de unos" no se refiere realmente a una operación, sino a un sistema de almacenamiento de enteros en bits. Un sistema que no se usa realmente en un sistema informático.
McKay