简体   繁体   中英

How do I do a bitwise Not operation in Python?

In order to test building an Xor operation with more basic building blocks (using Nand, Or, and And in my case) I need to be able to do a Not operation. The built-in not only seems to do this with single bits. If I do:

x = 0b1100
x = not x

I should get 0b0011 but instead I just get 0b0 . What am I doing wrong? Or is Python just missing this basic functionality?

I know that Python has a built-in Xor function but I've been using Python to test things for an HDL project/course where I need to build an Xor gate. I wanted to test this in Python but I can't without an equivalent to a Not gate.

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

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.

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

试试这个,它被称为按位补码运算符

~0b1100

string of binary can be used to preserve the left 0s, since we know that:

bin(0b000101) # '0b101'
bin(0b101)    # '0b101'

This function will return string format of the NOT of input number

def not_bitwise(n):
     ''' 
     n: input string of binary number (positive or negative)
     return: binary number (string format)
     '''
     head, tail = n.split('b')
     not_bin = head+'b'+tail.replace('0','a').replace('1','0').replace('a','1')
     return not_bin

Example:

In[266]: not_bitwise('0b0001101')
Out[266]: '0b1110010'

In[267]: int(not_bitwise('0b0001101'), 2)

Out[267]: 114

In[268]: not_bitwise('-0b1010101')

Out[268]: '-0b0101010'

In[269]: int(not_bitwise('-0b1010101'), 2)
Out[269]: -42

The answers here collectively have great nuggets in each one, but all do not scale well with depending on edge cases.

Rather than fix upon an 8-bit mask or requiring the programmer to change how many bits are in the mask, simply create a mask based on input via bit_length() :

def bit_not(num):
    return num ^ ((1 << num.bit_length()) - 1)

The general form given by John La Rooy, can be simplified in this way (python == 2.7 and >=3.1):

def bit_not(n):
    return (1 << n.bit_length()) - 1 - n

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM