How do I do a bitwise Not operation in Python?

Another way to achieve this, is to assign a mask like this (should be all 1's):

mask = 0b1111

Then xor it with your number like this:

number = 0b1100
mask = 0b1111
print(bin(number ^ mask))

You can refer the xor truth table to know why it works.


Try this, it's called the bitwise complement operator:

~0b1100

The problem with using ~ in Python, is that it works with signed integers. This is also the only way that really makes sense unless you limit yourself to a particular number of bits. It will work ok with bitwise math, but it can make it hard to interpret the intermediate results.

For 4 bit logic, you should just subtract from 0b1111

0b1111 - 0b1100  # == 0b0011

For 8 bit logic, subtract from 0b11111111 etc.

The general form is

def bit_not(n, numbits=8):
    return (1 << numbits) - 1 - n

Python bitwise ~ operator invert all bits of integer but we can't see native result because all integers in Python has signed representation.

Indirectly we can examine that:

>>> a = 65
>>> a ^ ~a
-1

Or the same:

>>> a + ~a
-1

Ther result -1 means all bits are set. But the minus sign ahead don't allow us to directly examine this fact:

>>> bin(-1)
'-0b1'

The solution is simple: we must use unsigned integers. First way is to import numpy or ctypes modules wich both support unsigned integers. But numpy more simplest using than ctypes (at least for me):

import numpy as np
a = np.uint8(0b1100)
y = ~x

Check result:

>>> bin(x)
'0b1100'
>>> bin(y)
'0b11110011'

And finally check:

>>> x + y
255

Unsigned integer '255' for 8-bits integers (bytes) mean the same as '-1' becouse has all bits set to 1. Make sure:

>>> np.uint8(-1)
255

And another simplest solution, not quite right, but if you want to include additional modules, you can invert all bits with XOR operation, where second argument has all bits are set to 1:

a = 0b1100
b = a ^ 0xFF

This operation will also drop most significant bit of signed integer and we can see result like this:

>>> print('{:>08b}'.format(a))
00001100
>>> print('{:>08b}'.format(b))
11110011

Finally solution contains one more operation and therefore is not optimal:

>>> b = ~a & 0xFF
>>> print('{:>08b}'.format(b))
11110011

Tags:

Python