Welcome, guest | Sign In | My Account | Store | Cart

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

Python, 24 lines
 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'

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.

8 comments

Scott David Daniels 20 years, 5 months ago  # | flag

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.

W.J. van der Laan 20 years, 4 months ago  # | flag

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)))
seb bacon 19 years, 1 month ago  # | flag

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)))
Benjamin Wiley Sittler 15 years, 2 months ago  # | flag

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)
Benjamin Wiley Sittler 15 years, 2 months ago  # | flag

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

Benjamin Wiley Sittler 15 years, 2 months ago  # | flag

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)]()
Benjamin Wiley Sittler 15 years, 2 months ago  # | flag

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)
Vishal Sapre 14 years, 8 months ago  # | flag

Here's another one: This one is better than most run time computation based methods, thanks to the efficient dictionary look up in Python: http://code.activestate.com/recipes/576847/

Created by Antti Kaihola on Tue, 2 Sep 2003 (PSF)
Python recipes (4591)
Antti Kaihola's recipes (1)
Python Cookbook Edition 2 (117)

Required Modules

  • (none specified)

Other Information and Tasks