137

In Python console:

~True

Gives me:

-2

Why? Can someone explain this particular case to me in binary?

Luke Willis
  • 8,429
  • 4
  • 46
  • 79
lukaszkups
  • 5,790
  • 9
  • 47
  • 85
  • 23
    because `~1` is `-2`, Try: `True == 1` – Grijesh Chauhan Feb 19 '14 at 13:06
  • 16
    Just to be precise: it is not true that "`True is 1`", but is is true that `True == 1`. – Bach Feb 19 '14 at 13:11
  • 3
    Do you really think seeing `UNARY_INVERT` (the whole of the bytecode) will add anything to answers? – Wooble Feb 19 '14 at 13:16
  • 2
    This question is **not** a duplicate! It asks about a specific behaviour of `bool`. It's not about how `~` works. In fact a valid answer to this question could avoid mentioning 2's complement and how `~` operates on integers at all. – Bakuriu Feb 19 '14 at 21:59
  • See also: [Why when 127*2 the result is -2 when we change to byte?](http://stackoverflow.com/questions/19785792) – hippietrail Feb 20 '14 at 07:40

3 Answers3

245

int(True) is 1.

1 is:

00000001

and ~1 is:

11111110

Which is -2 in Two's complement1

1 Flip all the bits, add 1 to the resulting number and interpret the result as a binary representation of the magnitude and add a negative sign (since the number begins with 1):

11111110 → 00000001 → 00000010 
         ↑          ↑ 
       Flip       Add 1

Which is 2, but the sign is negative since the MSB is 1.


Worth mentioning:

Think about bool, you'll find that it's numeric in nature - It has two values, True and False, and they are just "customized" versions of the integers 1 and 0 that only print themselves differently. They are subclasses of the integer type int.

So they behave exactly as 1 and 0, except that bool redefines str and repr to display them differently.

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

>>> True == 1
True
>>> True is 1  # they're still different objects
False
Maroun
  • 94,125
  • 30
  • 188
  • 241
  • 1
    @ofcapl Just wanted to say: Although `int('1')` is also `1` but `~'1'` be a typeerror exception whereas `~True` is not this is because `bool` is a subclass of `int` @ Martijn added this information in his answer. – Grijesh Chauhan Feb 19 '14 at 13:35
  • For the record, @ofcapl, this answer shows the binary arithmetic interpretation of what's going on, not the actual [bytecode](http://en.wikipedia.org/wiki/Bytecode) (which would be some sort of intermediate or operation level code compiled from the source). – Patrick M Feb 19 '14 at 15:53
  • Why is True=1 instead of -1, as it is in virtually every other language? (Sorry, PEP Index is currently out of service) – Flávio Etrusco Feb 19 '14 at 23:17
  • 5
    @etrusco what languages are you talking about? I know exactly 0 where `True == -1`, and I know many where one could say that `True == 1`... – l4mpi Feb 20 '14 at 09:19
  • 1
    @etrusco @l4mpi Some old-school BASICs use `-1` for TRUE; it has the nice property that the bitwise AND and OR operators work for logical AND and OR as well (`x & -1` is non-zero in the same cases that `x && 1` is non-zero in C), as long as you don't care about short-circuiting. However, as far as I know, no mainstream language has ever used `-1` for TRUE. – Quuxplusone Feb 20 '14 at 19:56
  • 1
    Formal logic defines `truth` as univalued; with all that is not `true` being `false`. All programming languages that I'm aware of turn formal logic on its head, defining `false` as univalued (0) and all that is not false being `true`). For instance [C#](http://msdn.microsoft.com/en-us/library/h0b8dwce(v=vs.110).aspx), though Javascript is something of an outlier, having multiple flavors of truthiness and [multiple flavors of falsiness](http://javascript.crockford.com/survey.html). – Nicholas Carey Feb 20 '14 at 20:27
45

The Python bool type is a subclass of int (for historical reasons; booleans were only added in Python 2.3).

Since int(True) is 1, ~True is ~1 is -2.

See PEP 285 for why bool is a subclass of int.

If you wanted the boolean inverse, use not:

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

If you wanted to know why ~1 is -2, it's because you are inverting all bits in a signed integer; 00000001 becomes 1111110 which in a signed integer is a negative number, see Two's complement:

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

where the initial 1 bit means the value is negative, and the rest of the bits encode the inverse of the positive number minus one.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    @GrijeshChauhan: For two's compliment, you could use `struct.pack`, as `bin(integer)` or `format(integer, '08b')` don't take signed integers into account. – Martijn Pieters Feb 19 '14 at 13:16
  • @thefourtheye , MartijnPieters I Tried But it is confusing e.g. `bin(~True)`, `bin(-2)`, `bin(~1)` all gives `'-0b10'` If `-2` representation is `10` then why `-` sign. – Grijesh Chauhan Feb 19 '14 at 13:19
  • What I mean `10` itself 2'complement then -ve? – Grijesh Chauhan Feb 19 '14 at 13:21
  • Ok Understood... 10 can be three Thanks! – Grijesh Chauhan Feb 19 '14 at 13:25
  • 1
    @GrijeshChauhan You can get the two's complement notation of both negative and positive numbers like this `format(-2 % (1 << 32), "032b")` – thefourtheye Feb 19 '14 at 13:26
  • 2
    @thefourtheye: I'd use a bitmask: `format(-2 & ((1 << 32) - 1), "032b")` – Martijn Pieters Feb 19 '14 at 13:28
  • There's a small step missing in your explanation (and in the other answer as well). The fact that `bool` subclasses `int` doesn't imply that `~True` must be `-2`. The fact that `bool` is a subclass of `int` that overrides *only* `&`, `|` and `^` does, which might not be obvious. – Bakuriu Feb 19 '14 at 21:56
  • @Bakuriu: Ah, I'll have to take that back; `bool` does override those methods, to make sure to call `super(bool, self).____(other)` if either `self` or `other` is not a `bool` instance. – Martijn Pieters Feb 19 '14 at 22:40
  • @Bakuriu: But I think it hardly matters here; `__invert__` is not implemented which is what *would* matter here. – Martijn Pieters Feb 19 '14 at 22:43
4

~True == -2 is not surprising if True means 1 and ~ means bitwise inversion...

...provided that

  • True can be treated as an integer and
  • integers are represented in Two's complement

Edits:

  • fixed the mixing between integer representation and bitwise inversion operator
  • applied another polishing (the shorter the message, the more work needed)
Wolf
  • 9,679
  • 7
  • 62
  • 108
  • 2
    `~` does not mean "2s complement". `~` means "Bitwise Inversion" – McKay Feb 20 '14 at 14:18
  • 1
    The phrase "Ones' complement" doesn't really refer to an operation, as much as it refers to a system of storing integers in bits. A system that isn't actually used in a computer system. – McKay Feb 20 '14 at 14:27