11

I have the following scenario:

x = 0b0111

I would like to convert this value to:

y = [0, 1, 1, 1]

When I convert x = 0b1001, I can get y = [1, 0, 0, 1], but when I try to do the same for x = 0b0111, and then convert back with str(bin(y)) - I seem to lose the leading 0, and get 0b111.

Any suggestions?

1
  • 1
    0b0111 == 0b111 so what's the problem? If you need the lists to be fixed length, then just tack on the appropriate amount of 0's to the beginning. Commented Oct 26, 2012 at 5:15

11 Answers 11

10

Once you get that string 0b111, it's straightforward to split out the digits that you're interested in. For each character of everything after the 0b in the string, convert it to an integer.

[int(d) for d in str(bin(x))[2:]]
Sign up to request clarification or add additional context in comments.

1 Comment

The object returned by bin(x) is of type <class 'str'>, I think we don't need to explicitly convert it to str() again and this should work: [int(d) for d in bin(x)[2:]]
5

For what it's worth, a pure arithmetic solution appears to be marginally faster:

import timeit

def bits1(n):
    b = []
    while n:
        b = [n & 1] + b
        n >>= 1
    return b or [0]

timeit.timeit(lambda: bits1(12345678))
[out] 7.717339038848877

def bits2(n):
    return [int(x) for x in bin(n)[2:]]


timeit.timeit(lambda: bits2(12345678))
[out] 10.297518014907837

2019 update: In python 3.7.3 the second version is slightly faster.

2 Comments

For python 3 you should move the list from inside the map to outside the map. You can also win some performance by using b.append(n&1) rather than b = [n & 1] + b. Unfortunately(?) in my case the bits2 option is 10 times faster than the pure version.
@ThomasAhle: thanks, the bits2 version edited. In py3 it's slightly faster, but not as much as 10x.
4

Updated for f-String:

x = 0b0111
y = [int(i) for i in f'{x:04b}']

y = [0, 1, 1, 1]

or:

x = 0b0111 # binary representation of int 7
n_bits = 4 # desired bits' len
y = [int(i) for i in f'{x:0{n_bits}b}']

Will populate a list of minimum len n-bits filling the list with leading 0's

Comments

3

First convert the number to binary and then to string:

str(bin(7))
'0b111' #note the 0b in front of the binary number

Next, remove the 0b from the string

str(bin(7))[2:]
'111'

Finally we use list comprehension to create a list of ints from the string, which has roughly the following form:

[expr for i in iterable]
[int(i) for i in str(bin(x))[2:]]

Comments

3

An expression like map(int, list(bin((1<<8)+x))[-4:]) will give you the low 4 bits of a number, as a list. (Edit: A cleaner form is map(int,bin(x)[2:].zfill(4)) ; see below.) If you know how many bits you wish to show, replace the 4 (in [-4:]) with that number; and make the 8 (in (1<<8)) a larger number if necessary. For example:

>>> x=0b0111
>>> map(int,list(bin((1<<8)+x))[-4:])
[0, 1, 1, 1]
>>> x=37; map(int,list(bin((1<<8)+x))[-7:])
[0, 1, 0, 0, 1, 0, 1]
>>> [int(d) for d in bin((1<<8)+x)[-7:]]
[0, 1, 0, 0, 1, 0, 1]

The last example above shows an alternative to using map and list. The following examples show a slightly cleaner form for obtaining leading zeroes. In these forms, substitute the desired minimum number of bits in place of 8.

>>> x=37; [int(d) for d in bin(x)[2:].zfill(8)]
[0, 0, 1, 0, 0, 1, 0, 1]
>>> x=37; map(int,bin(x)[2:].zfill(8))
[0, 0, 1, 0, 0, 1, 0, 1]
>>> x=37; map(int,bin(x)[2:].zfill(5))
[1, 0, 0, 1, 0, 1]
>>> x=37; map(lambda k:(x>>-k)&1, range(-7,1))
[0, 0, 1, 0, 0, 1, 0, 1]

Comments

2

If the length of bits is fixed to 4, there are two solutions:

[int(i) for i in '{0:04b}'.format(0b0111)]

or with NumPy,

import numpy as np
[int(i) for i in np.binary_repr(0b0111, 4)]

Comments

0

check this simple way to do it... for this particular scenario

In [41]: x=0b0111

In [42]: l = [0,0,0,0]

In [43]: counter = -1

In [44]: for i in str(bin(x))[2:]:
   ....:     l[counter] = i
   ....:     counter = counter -1
   ....:

In [45]: l
Out[45]: [0, '1', '1', '1']

Comments

0
c=[]
for i in bin(7)[2:]: 
        c.append(int(i)) #turning string "111", to 111
if len(c)==3:
    c.insert(0,0)
print(c)

# binary digit 7 produces '0b111' by this slicing[2:], result get '111'

so if element in list c is 3, 0 is inserted first.

1 Comment

Kindly Post some explanation of the answer as well.
0

Not very pythonian but:

byte = 0b00011001
arr = []
for i in range(7, -1, -1):
    arr.append((byte & 1<<i)>>i)
print(arr)

[0, 0, 0, 1, 1, 0, 0, 1]

this uses bitmasking to "extract" each bit and append to an array.

Comments

0

Given a number value and number of bits to represent it in width:

string = format(value, '0{}b'.format(width))
binary_list = [0 if c == '0' else 1 for c in string]

This is about one third faster than binary_list = [int(c) for c in string]

Comments

0

Here is a simple on-liner with no string parsing needed:

[x >> bin_idx & 1 for bin_idx in reversed(range(x.bit_length()))]

I believe it's a bit faster than other answers posted here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.