# Python Bitwise NOT Operator

Python’s bitwise NOT operator `~x` inverts each bit from the binary representation of integer `x` so that 0 becomes 1 and 1 becomes 0. This is semantically the same as calculating `~x == -x-1`. For example, the bitwise NOT expression `~0` becomes `-1`, `~9` becomes `-10`, and `~32` becomes `-33`.

As you go over the article, you can watch my explainer video here:

In this example, you apply the bitwise NOT operator to integer 32:

```>>> ~32
-33```

The expression `~32` operates on the bit representations `"0100000"` (decimal 32) and performs bitwise NOT resulting in binary `"1011111"`. This corresponds to the negative decimal number -33.

How do you transform the binary “1011111” to a decimal number again? By using the following steps:

• Flip each bit back to `0100000`.
• Get the corresponding decimal number `32`.
• Increase it by one to `33`.
• Prefix it with the negative symbol `-33`.

To understand this inverse method from a negative binary to an integer, you need to learn some background first. But don’t worry, it’s just a couple of minutes! ?

## Representing Negative Integers in Binaries

Python uses so-called complementary binaries to represent negative integers. The first bit of a complementary binary is the sign (0: positive, 1: negative). All remaining bits encode the number. You write a negative number `-x` as the bit pattern for `(x-1)` and flip all bits from 1 to 0 and from 0 to 1 (complement).

Here are two simple examples:

• To represent `x = -1` using 8 bits you first calculate `(1-1) = 0` and then flip all bits to calculate `"11111111"`.
• To represent `x = -10` using 8 bits you first calculate `(10-1) = 9` which is `"00001001"` in binary format. Then, you complement all bits to determine the negative (complementary) binary `"11110110"`.

? In fact, Python uses signed integers for its bitwise operators. You may ask: what are signed integers?

• A signed integer, for example using 32 bits, encodes an integer in the range `[-2147483648 to 2147483647]`.
• An unsigned integer encodes a positive integer in the range `[0 to 4294967295]`. The signed integer is represented in twos complement notation.

## Python Bitwise NOT Operator Example

Here’s the result of the bitwise NOT operator `~x` when applied to a couple of example integer operands `x`:

You can see those examples in the following Python script:

```>>> ~0
-1
>>> ~1
-2
>>> ~3
-4
>>> ~9
-10
>>> ~11
-12
>>> ~256
-257```

Let’s use this knowledge in a couple of examples to showcase the working of the bitwise NOT operator on negative integers:

## Python Bitwise NOT Examples on Negative Integers

Here’s the result of the bitwise NOT operator `~x` when applied to a negative integer operand `x`:

You can see those examples in the following script:

```>>> ~-0
-1
>>> ~-1
0
>>> ~-3
2
>>> ~-9
8
>>> ~-11
10
>>> ~-256
255```

You can define your own bitwise NOT operator on a custom class by overloading the `__invert__` method (dunder method, magic method) with a reference to `self` as an argument. This allows the expression `~x` on your custom objects without raising an error.

Here’s an example:

```class Data:
def __init__(self, data):
self.data = data

def __invert__(self):
return Data(~self.data)

x = Data(3)

res = ~x
print(res.data)
# -4
```

Note: if you forget to overwrite the `__invert__` method and still try to use the expression `~x`, Python will raise a `TypeError: bad operand type for unary ~`. You can fix it by defining the dunder method `__invert__(self)` in your class definition.

```class Data:
def __init__(self, data):
self.data = data

x = Data(3)

res = ~x
print(res.data)```

Output:

```Traceback (most recent call last):
File "C:\Users\xcent\Desktop\code.py", line 8, in
res = ~x
TypeError: bad operand type for unary ~: 'Data'```

To fix this `TypeError`, simply define the `__invert__` method as shown in the previous working example.

## Bitwise Operators

Bitwise operators perform operations on the binary (bit) representation of integers. The following table gives a short overview of all existing bitwise operators. Note that we also provide the binary representation `100` for the decimal integer `4`, and `101` for the decimal integer `5` as a comment in the right column.

Here’s a short overview of the Bitwise operators’ magic methods:

Here’s an example of how to accomplish these bitwise operators on a custom class `Data`. We marked this respective operator in the code:

```class Data:

def __init__(self, data):
self.data = data

def __and__(self, other):
return Data(self.data & other.data)

def __or__(self, other):
return Data(self.data | other.data)

def __xor__(self, other):
return Data(self.data ^ other.data)

def __invert__(self):
return Data(~self.data)

def __lshift__(self, other):
return Data(self.data << other.data)

def __rshift__(self, other):
return Data(self.data >> other.data)

x = 2
y = 3
print('Operands: \n', 'x =', x, '\n', 'y =', y)
print()
print('Bitwise AND: ', x & y)
print('Bitwise OR: ', x | y)
print('Bitwise XOR: ', x ^ y)
print('Bitwise NOT: ', ~x)
print('Bitwise LEFT-SHIFT: ', x << y)
print('Bitwise RIGHT-SHIFT: ', x >> y)
```

The output is:

```Operands:
x = 2
y = 3

Bitwise AND:  2
Bitwise OR:  3
Bitwise XOR:  1
Bitwise NOT:  -3
Bitwise LEFT-SHIFT:  16
Bitwise RIGHT-SHIFT:  0```