Question

I wish to do bitwise negation in Python.

My expectation:

negate(0001) => 1110

But Python's ~0b0001 returns -0b10. It seems Python truncate 1110 into -0b10.

How to keep the leading bits?

Moreover, why

bin(~0b1) yields -0b10?

How many bits are reserved for that datatype?

Was it helpful?

Solution

Python uses arbitrary precision arithmetic, so you don't have to worry about the number of bits used. Also it returns -0b10 for bin(~0b1), because it understands that the result is -2 and represents the number as it is 10 and keeps the sign in the front (only for the negative numbers).

But we can represent the number as we like using format function, like this

def negate(number, bits = 32):
    return format(~number & 2 ** bits - 1, "0{}b".format(bits))

print(negate(1))
# 11111111111111111111111111111110
print(negate(1, bits = 4))
# 1110

Or, as suggested by eryksun,

def negate(number, bits = 32):
    return "{:0{}b}".format(~number & 2 ** bits - 1, bits)

OTHER TIPS

Python acts as if its integers have infinitely many bits. As such, if you use ~ on one, the string representation can't start with an infinite number of 1s, or generating the string would never terminate. Instead, Python chooses to represent it as a negative number as it would be using two's compliment. If you want to restrict the integer to a number of bits, & it against an appropriate mask:

>>> bin((~1) & 0b1111)
'0b1110'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top