I need to do a "~" operation in Python but not taking account of 2's complement. I managed to do that by using XOR, do you know another way to do this? (more efficient)
a = 0b101
b = 0b10101
print bin(a ^ (2 ** a.bit_length() - 1)) #0b10
print bin(b ^ (2 ** b.bit_length() - 1)) #0b1010
That's what ~
does already. The tricky part is that Python has unlimited length integers, so when you invert a number it is sign extended with--at least conceptually speaking--an infinite number of 1's. Meaning you get negative numbers.
>>> bin(~0b101)
'-0b110'
>>> bin(~0b10101)
'-0b10110'
To convert these to unsigned numbers, you need to decide how many bits you care about. Maybe you are working with 8-bit bytes. Then you could AND them with a byte's worth of 1 bits:
>>> bin(~0b101 & 0xFF)
'0b11111010'
>>> bin(~0b10101 & 0xFF)
'0b11101010'
Or if you want to match the exact bit length of the input numbers, your solution is reasonable. For efficiency you could switch the exponent for a left shift. And it might be clearer to use ~
and &
instead of ^
.
>>> bin(~a & ((1 << a.bit_length()) - 1))
'0b10'
>>> bin(~b & ((1 << b.bit_length()) - 1))
'0b1010'
(I suspect a hardcoded mask like & 0xFFFF
will be the right solution in practice. I can't think of a good real world use case for the bit_length()
-based answer.)