Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert an integer to a list of bits?

Tags:

python

I'm trying to represent an integer as a list of bits and left pad it to 8 bits only if the integer is < 128:

Example input: 0x15
Desired output: [0, 0, 0, 1, 0, 1, 0, 1]

I do it in the following way:

input = 0x15
output = deque([int(i) for i in list(bin(input))[2:]])
while len(output) != 8:
    output.appendleft(0)

I would like to convert any integer to a binary-list. Pad to 8 only if the number requires less than 8 bits to represent.

Another Example input: 0x715
Desired output: [1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]

How can I do this both for numbers less then 8 bits and also for larger ones?

like image 629
Subbdue Avatar asked Jun 22 '15 01:06

Subbdue


People also ask

How many bits is a integer?

Integer, 16 bit Unsigned data type is used for numerical tags where only positive variables will be used.

How do you convert numbers to bits in Python?

In Python, we can simply use the bin() function to convert from a decimal value to its corresponding binary value. The bin() takes a value as its argument and returns a binary equivalent. Note: bin() return binary value with the prefix 0b, so depending on the use-case, formatting should be done to remove 0b.

How do you convert a list of integers to a list in Python?

Use the join() method of Python. First convert the list of integer into a list of strings( as join() works with strings only). Then, simply join them using join() method. It takes a time complexity of O(n) .

How do you convert a list of integers to a list of strings?

The most Pythonic way to convert a list of integers ints to a list of strings is to use the one-liner strings = [str(x) for x in ints] . It iterates over all elements in the list ints using list comprehension and converts each list element x to a string using the str(x) constructor.


6 Answers

For a fixed size of 8 bits:

num = 0x15
out = [1 if num & (1 << (7-n)) else 0 for n in range(8)]

The (1 << (7-n)) creates a single bit mask for a given position, and then bitwise & tests to see if that bit is set in the number. Having n work through 0 to 7 results in all 8 bits in the byte being tested in order.

For arbitrarily sized numbers:

import math
num = 0x715
bits = int(max(8, math.log(num, 2)+1))
out = [1 if num & (1 << (bits-1-n)) else 0 for n in range(bits)]
like image 69
Amber Avatar answered Oct 05 '22 08:10

Amber


>>> [int(n) for n in bin(0x15)[2:].zfill(8)]
[0, 0, 0, 1, 0, 1, 0, 1]

The slice [2:] is to remove 0b prefix, zfill(8) is to pad zeros on the left.

like image 27
Yu Hao Avatar answered Oct 05 '22 09:10

Yu Hao


number = 0x15

output = [int(x) for x in '{:08b}'.format(number)]

'{:08b}'.format(number) represents your number in binary format with 0 padding to 8 digits, then using list comprehension to create a list of bits.

Alternatively, you can use map function:

output = map(int, '{:08b}'.format(0x15))

If you want to use a variable number of bits, here is one way:

width = 8  # 8bit width
output = [int(x) for x in '{:0{size}b}'.format(0x15, size=width)]
output = map(int, '{:0{size}b}'.format(0x15, size=width))

For Python 3, wrap the map(...) call with list() (map returned a list in Python 2 but returns an iterator in 3).

like image 20
Iron Fist Avatar answered Oct 05 '22 08:10

Iron Fist


Solution

Works for any number of bits, faster than the accepted answer and the current highest voted answer:

num = 0xAAAA
bit_list = [(num >> shift_ind) & 1
             for shift_ind in range(num.bit_length())] # little endian
bit_list.reverse() # big endian
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

Timings

from timeit import timeit

def accepted_answer(number):
    output = [int(x) for x in '{:08b}'.format(number)]

    return output

def highest_voted_answer(num):
    out = [1 if num & (1 << (7-n)) else 0 for n in range(8)]

    return out

def this_answer(num):
    bit_list = [(num >> shift_ind) & 1
                for shift_ind in range(num.bit_length())] # little endian
    bit_list.reverse() # big endian

    return bit_list

NUM = 0x15
ITERATIONS = int(1e7)

print(timeit(lambda: accepted_answer(NUM), number=ITERATIONS))
print(timeit(lambda: highest_voted_answer(NUM), number=ITERATIONS))
print(timeit(lambda: this_answer(NUM), number=ITERATIONS))
9.884788331000891
9.262861715000327
6.484631327999523
like image 23
young_souvlaki Avatar answered Oct 05 '22 08:10

young_souvlaki


It's easy to do this with format strings

>>> "{:08b}".format(0x15)
'00010101'
>>> "{:08b}".format(0x151)
'101010001'
>>> "{:08b}".format(0x1511)
'1010100010001'

to convert to a list

>>> [1 if x=='1' else 0 for x in "{:08b}".format(0x15)]
[0, 0, 0, 1, 0, 1, 0, 1]
>>> [1 if x=='1' else 0 for x in "{:08b}".format(0x1511)]
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]

It's likely to be faster using bit twiddling as in @Amber's answer, but then you'll have to check for special cases and end up with quite a bit of code. If utmost performance isn't required, it's safer to build on what you know already works

like image 42
John La Rooy Avatar answered Oct 05 '22 10:10

John La Rooy


np.unpackbits(np.frombuffer(number, np.dtype('B')))
like image 40
Jerzy Orłowski Avatar answered Oct 05 '22 09:10

Jerzy Orłowski