Two's Complement in Python
Two's complement subtracts off (1<<bits)
if the highest bit is 1. Taking 8 bits for example, this gives a range of 127 to -128.
A function for two's complement of an int...
def twos_comp(val, bits): """compute the 2's complement of int value val""" if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255 val = val - (1 << bits) # compute negative value return val # return positive value as is
Going from a binary string is particularly easy...
binary_string = '1111' # or whatever... no '0b' prefixout = twos_comp(int(binary_string,2), len(binary_string))
A bit more useful to me is going from hex values (32 bits in this example)...
hex_string = '0xFFFFFFFF' # or whatever... '0x' prefix doesn't matterout = twos_comp(int(hex_string,16), 32)
It's not built in, but if you want unusual length numbers then you could use the bitstring module.
>>> from bitstring import Bits>>> a = Bits(bin='111111111111')>>> a.int-1
The same object can equivalently be created in several ways, including
>>> b = Bits(int=-1, length=12)
It just behaves like a string of bits of arbitrary length, and uses properties to get different interpretations:
>>> print a.int, a.uint, a.bin, a.hex, a.oct-1 4095 111111111111 fff 7777
Since Python 3.2, there are built-in functions for byte manipulation: https://docs.python.org/3.4/library/stdtypes.html#int.to_bytes.
By combining to_bytes and from_bytes, you get
def twos(val_str, bytes): import sys val = int(val_str, 2) b = val.to_bytes(bytes, byteorder=sys.byteorder, signed=False) return int.from_bytes(b, byteorder=sys.byteorder, signed=True)
Check:
twos('11111111', 1) # gives -1twos('01111111', 1) # gives 127
For older versions of Python, travc's answer is good but it does not work for negative values if one would like to work with integers instead of strings. A twos' complement function for which f(f(val)) == val is true for each val is:
def twos_complement(val, nbits): """Compute the 2's complement of int value val""" if val < 0: val = (1 << nbits) + val else: if (val & (1 << (nbits - 1))) != 0: # If sign bit is set. # compute negative value. val = val - (1 << nbits) return val