ActiveState Code

Recipe 219300: Format integer as binary string


These one-liner lambdas convert integers to binary strings with no leading zeros.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# bstr_pos: only positive integers
# zero     -> ''
# negative -> ''

bstr_pos = lambda n: n>0 and bstr_pos(n>>1)+str(n&1) or ''

# bstr_nonneg: only non-negative integers
# zero     -> '0'
# negative -> ''

bstr_nonneg = lambda n: n>0 and bstr_nonneg(n>>1).lstrip('0')+str(n&1) or '0'

# bstr_sgn: all integers, signed
# zero -> '0'
# negative get a minus sign

bstr_sgn = lambda n: n<0 and '-'+binarystr(-n) or n and bstr_sgn(n>>1).lstrip('0')+str(n&1) or '0'

# bstr: all integers
# zero -> '0'
# negative represented as complements, 16-bit by default
# optional second argument specifies number of bits

bstr = lambda n, l=16: n<0 and binarystr((2L<<l)+n) or n and bstr(n>>1).lstrip('0')+str(n&1) or '0'

Discussion

I wanted to have a short cut-and-paste solution for representing integers as binary strings. As a result, these functions are by no means clear or readable.

The string concatenation method used here is quite slow. A faster approach would be to output digits directly to a file-like object, or maybe first construct a list and then make a string by joining it.

Comments

  1. 1. At 7:59 p.m. on 24 oct 2003, Scott David Daniels said:

    If you can use a data table, use octal conversion. If you define a table:

    asbits = dict([(v[0], v[1:4]) for v in ['0000', '1001',
                  '2010', '3011', '4100', '5101','6110','7111']])
    

    Then

    bstr_pos = lambda x: ''.join([asbits[ch] for ch in oct(x)]).lstrip('0')
    

    might do the job. But I don't understand why:

    def bstr_pos(x) return ''.join([asbits[ch] for ch in oct(x)]).lstrip('0')
    

    is worse.

  2. 2. At 10:52 a.m. on 5 nov 2003, W.J. van der Laan said:

    Binary with fixed length.

    def tobin(x, count=8):
            """
            Integer to binary
            Count is number of bits
            """
            return "".join(map(lambda y:str((x>>y)&amp;1), range(count-1, -1, -1)))
    
  3. 3. At 8:22 a.m. on 17 feb 2005, seb bacon said:

    binary to decimal oneliner. Inverse of the previous...

    def toDecimal(x):
        return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
                       range(len(x)-1, -1, -1)))
    
  4. 4. At 10:46 p.m. on 9 jan 2009, Benjamin Wiley Sittler said:

    I like bin() from Python 2.6, but it doesn't exist in Python 2.5. So I use this simple but inefficient replacement:

    try:
        if bin(0):
            pass
    except NameError, ne:
        bin = lambda x: [lambda x:'-'+bin(0-x),
                         lambda x:'0b0',
                         lambda x:'0b'+'01'[x&1],
                         lambda x:'0b'+bin(x>>1)[2:]+'01'[x&1]
                        ][1+(x>1)+(x>0)-(x<0)](x)
    
  5. 5. At 10:54 p.m. on 9 jan 2009, Benjamin Wiley Sittler said:

    note that the list of lambdas [ ... ] can be replaced by a tuple of lambdas ( ... ) in my example

  6. 6. At 11:49 p.m. on 9 jan 2009, Benjamin Wiley Sittler said:

    trying to print more than a few hundred bits at once using the recursive version is likely to exceed the maximum recursion depth. so here's a non-recursive version equivalent to the Python 2.6 bin() which should work all the way back to Python 2.3:

    try:
        if bin(0): pass
    except NameError, ne:
        def bin(x):
            """
            bin(number) -> string
    
            Stringifies an int or long in base 2.
            """
            if x < 0: return '-' + bin(-x)
            out = []
            while x > 0:
                out.append('01'[x & 1])
                x >>= 1
            if x == 0: out.append('0')
            try: return '0b' + ''.join(reversed(out))
            except NameError, ne2: out.reverse()
            return '0b' + ''.join(out)
    

    and here's a simplified version of the recursive version:

    try:
        if bin(0): pass
    except NameError, ne:
        bin = lambda x: (
            lambda: '-' + bin(-x),
            lambda: '0b' + '01'[x & 1],
            lambda: bin(x >> 1) + '01'[x & 1]
            )[1 + (x > 1) - (x < 0)]()
    
  7. 7. At 11:53 p.m. on 9 jan 2009, Benjamin Wiley Sittler said:

    sorry, left one line out of place when reformatting for that post:

    def bin(x):
        """
        bin(number) -> string
    
        Stringifies an int or long in base 2.
        """
        if x < 0: return '-' + bin(-x)
        out = []
        if x == 0: out.append('0')
        while x > 0:
            out.append('01'[x & 1])
            x >>= 1
            pass
        try: return '0b' + ''.join(reversed(out))
        except NameError, ne2: out.reverse()
        return '0b' + ''.join(out)
    

Sign in to comment