Reputation: 845
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?
Upvotes: 21
Views: 26498
Reputation: 2066
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]
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
Upvotes: 5
Reputation: 1
I use bitmasks far less than I used to, but when I do use them I often have the need to decompose a value into its parts
def get_Bits(number):
i = 1
list_of_hex = []
while (i <= number):
if ((number & i) > 0):
bitRepresentation = hex(i)
list_of_hex.append(bitRepresentation)
i = i*2
return list_of_hex
you can change the (hex) function to (bin) if you need the binary decomposition
Upvotes: 0
Reputation: 10951
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).
Upvotes: 8
Reputation: 3036
from math import ceil
input = 0x15
bin_string = bin(input)[2:]
binary = map(int,bin_string.zfill(int(ceil(len(bin_string)/8.0)*8)))
print(binary)
This will round to nearest multiple of 8 , if u want to round to multiple of 8 only if <128, use a simple if else statement and remove zfill
in else
Output for 0x15:
[0, 0, 0, 1, 0, 1, 0, 1]
Output for 0x715:
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
If you only want to add zeros if less than 128, use this:
input = 0x715
bin_string = bin(input)[2:]
num_bits = (8 if input < 128 else 0)
binary = map(int,bin_string.zfill(num_bits))
print(binary)
Ouput for 0x15:
[0, 0, 0, 1, 0, 1, 0, 1]
Output for 0x715:
[1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
Upvotes: 0
Reputation: 11113
You can shift the number x steps to the right and then make a bitwise and the result with 1 to get the bit at position x
, do this with list-comprehension and you get your list. If you need to support negative numbers we may need to add a leading zero to the list to ensure that positive numbers doesn't start with a 1:
import math
def bits(n):
# The number of bits we need to represent the number
num_bits = max(8, int(math.log(abs(n), 2)) + 1)
# The bit representation of the number
bits = [ (n >> i) & 1 for i in range(num_bits) ]
bits.reverse()
# Do we need a leading zero?
if n < 0 or bits[0] == 0:
return bits
return [0] + bits
# Examples
for n in (-0x15, 0x15, 128, 255, 256, -256):
print("{: 4} = {}".format(n, bits(n)))
-21 = [1, 1, 1, 0, 1, 0, 1, 1] 21 = [0, 0, 0, 1, 0, 1, 0, 1] 128 = [0, 1, 0, 0, 0, 0, 0, 0, 0] 255 = [0, 1, 1, 1, 1, 1, 1, 1, 1] 256 = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0] -256 = [1, 0, 0, 0, 0, 0, 0, 0, 0]
Upvotes: 0
Reputation: 526683
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.
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)]
Upvotes: 15
Reputation: 304205
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
Upvotes: 4
Reputation: 122383
>>> [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.
Upvotes: 7