10

Is there an easy way to produce a one's complement in python?

For instance, if you take the hex value 0x9E, I need to convert it to 0x61.

I need to swap the binary 1's for 0's and 0's for 1's. It feels like this should be simple.

nbro
  • 15,395
  • 32
  • 113
  • 196
user1841870
  • 101
  • 1
  • 1
  • 3

2 Answers2

29

Just use the XOR operator ^ against 0xFF:

>>> hex(0x9E ^ 0xFF)
'0x61'

If you need to work with values larger than a byte, you could create the mask from the int.bit_length() method on your value:

>>> value = 0x9E
>>> mask = (1 << value.bit_length()) - 1
>>> hex(value ^ mask)
'0x61'
>>> value = 0x9E9E
>>> mask = (1 << value.bit_length()) - 1
>>> hex(value ^ mask)
'0x6161'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • OK I'm confused, why is `~x` wrong? It's supposed to be the binary negation operator after all. I can't wrap my mind over the lack of signed/unsigned distinction when binary ops are concerned – Kos Nov 21 '12 at 12:06
  • 2
    @Kos: `~` literally returns `-(x+1)`, which is great when dealing with signed values. So `~0x9E` is `-159`, or `-0x9f` hex. For unsigned bitwise work, not so great.. – Martijn Pieters Nov 21 '12 at 12:10
  • OK I got this, Python's "conceptually infinite string of `1`'s in front of negative numbers" approach has messed with my head. Analogies to C bitwise ops won't work here :( – Kos Nov 21 '12 at 12:18
  • @aka.nice: Sure, that works (I used `|` bitwise or accidentally). You still need to create the mask though. – Martijn Pieters Nov 21 '12 at 16:36
2

Hah. just found out that python bin() return a string!

so we can have some fun at this!

for x in numbers: # numbers is a list of int
    b = bin(x)
    #print b # e.g. String 0b1011100101
    b = b.replace('0', 'x')
    b = b.replace('1', '0')
    b = b.replace('x', '1')
    b = b.replace('1b', '0b')
    #print b # String 0b0100011010
    print int(b, 2) # the decimal representation
gcb
  • 13,901
  • 7
  • 67
  • 92