Binary numeral conversion (Python)

From LiteratePrograms

Jump to: navigation, search

It is easy to create an integer from a binary numeral in Python. The expression

int("10111001", base=2)

evaluates to 185 as expected. However, Python 2.x and earlier has no built-in support for going the other way: displaying an integer in binary. Python 2.6 and above has bin, oct, and hex functions in the built-in namespace.

Python does have the ability to display an integer in octal (with "%o" % n) or hexadecimal (with "%x" % n). We can utilize this to produce the binary representation by translating the octal digits one by one. We create a lookup table:

<<lookup table>>=
oct2bin = {'0': '000', '1': '001', '2': '010', '3': '011', '4': '100',
 '5': '101', '6': '110', '7': '111'}

The implementation is straightforward:

<<main function>>=
def bin(n):
    if n < 0:
        return "-" + bin(-n)
    # Build list of groups of three binary digits
    s = [oct2bin[octdigit] for octdigit in ("%o" % n)]
    # Merge list to single string and remove leading zeros
    s = "".join(s).lstrip("0")
    return s or "0"

A more canonical version that does not utilize a lookup table is also simple to implement. This method goes through the bits of the integer from least significant bit to most significant bit by examining whether the number is even or odd, then bit-shifting right one position. As we step through the bits by doing this, we also prepend a '1' or '0' to a string based on whether the number is even or odd.

<<alternate function>>=
def alt_bin(n):
    if n < 0:
        return "-" + alt_bin(-n)
    s = ''
    while n != 0:
        if n % 2 == 0: bit = '0'
        else: bit = '1'
        s = bit + s
        n >>= 1
    return s or '0'

A simple test driver:

if __name__ == "__main__":
    for i in range(-50, 50):
        assert i == int(bin(i), 2)
        assert i == int(alt_bin(i), 2)
lookup table
main function
alternate function