6

Why bitwise not does not act as expected for toggling bits? See for example below:

a = 5
print(bin(a))
b = ~a
print(bin(b))

This is the output:

0b101
-0b110

The question is why the first bit from the left is not toggled?

Considering that Python documentation says:

~ x Returns the complement of x - the number you get by switching each 1 for a 0 and each 0 for a 1.


Edit: Are you saying that "~" is not the operator for simple toggling of bits, but instead it is the operator for twos complement? If so, why the sentence quoted from documentation does not tell that. The sentence above from Python documentation does not imply this to me.

ascripter
  • 5,665
  • 12
  • 45
  • 68
user25004
  • 1,868
  • 1
  • 22
  • 47

1 Answers1

27

It is toggling all the bits. All of them, including an infinite number of leading zeros, producing an infinite number of leading ones:

0b...111111111111111111111111111111111111111111111111111010

because Python simulates an infinite-bit representation, not 3-bit or 32-bit or 64-bit or any finite number. Quoting the docs,

The result of bitwise operations is calculated as though carried out in two’s complement with an infinite number of sign bits.

Python can't show you an infinite number of leading ones, so instead, it shows you bin(abs(b)) with a - sign in front. abs(b) is 6 and bin(6) is '0b110', so you see

-0b110
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • this is a really good answer. Where did you get the info? – lmiguelvargasf Oct 04 '17 at 20:14
  • @lmiguelvargasf: It's hard to remember all the stuff I've read, but at least one of my sources was probably the [Python data model documentation](https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy), which says "For the purpose of shift and mask operations, a binary representation is assumed, and negative numbers are represented in a variant of 2’s complement which gives the illusion of an infinite string of sign bits extending to the left." – user2357112 Oct 04 '17 at 20:20