python3: How to get logical complement (negation) of a binary number, eg. '010' => '101'?
Maybe I'm missing something but I c开发者_StackOverflowan't find a straightforward way to accomplish this simple task. When I go to negate a binary number through the "~" operator it returns a negative number due to the two's complement:
>>> bin(~0b100010) # this won't return '0b011101'
'-0b100011'
What about if I just want to switch 0s into 1s and vice-versa, like in classic logical complement?
>>> bin(0b111111 ^ 0b100010)
'0b11101'
>>>
YOU's answer as a function:
def complement(n):
size = len(format(n, 'b'))
comp = n ^ ((1 << size) - 1)
return '0b{0:0{1}b}'.format(comp, size)
>>> complement(0b100010)
'0b011101'
I made it preserve the bit length of the original. The int constructor doesn't care about the leading zeros:
>>> complement(0b1111111100000000)
'0b0000000011111111'
>> int(complement(0b1111111100000000), 2)
255
Ultra nasty:
>>> '0b' + ''.join('10'[int(x)] for x in format(0b100010,'b')).lstrip('0')
'0b11101'
Here's another couple of functions that returns the complement of a number I came out with.
A one-liner:
def complement(c):
return c ^ int('1'*len(format(c, 'b')), 2)
A more mathematical way:
def complement(c):
n=0
for b in format(c, 'b'): n=n<<1|int(b)^1
return n
Moreover, one-linerizing this last one with functools (such baroque):
def complement(c):
return functools.reduce( lambda x,y: x<<1|y, [ int(b)^1 for b in format(c, 'b') ])
Finally, a uselessly nerdish variant of the first one that uses math.log to count the binary digits:
def complement(c):
c ^ int('1' * math.floor(math.log((c|1)<<1, 2)), 2)
Another function more a 'Hack' for complementing a Integer. You can use the same logic for complementing binary. Wonder why I did not come across python external libs that can do same. The next ver of Python should take care of this in built-ins
def complement(x):
b = bin(x)[2:] c= [] for num in b: if num == '1': c.append('0') elif num == '0': c.append('1') cat = ''.join(c) res = int(cat, 2) return print(res)
精彩评论