How to convert an integer to a list of bits? - 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?

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)]

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).

>>> [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.

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

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

np.unpackbits(np.frombuffer(number, np.dtype('B')))

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]

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]

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

Related

Fibonacci Adder Machine - Calculating Digits in Fibonacci Sequence

I'm working on a program that will calculate fibonacci numbers with certain digit limitations (i.e. first fibonacci number with 100 digits). The code I have below overall is running, but I am hitting a logical error that has me stumped.
The goal of the code is to calculate Fibonacci numbers in a fashion similar to binary addition. Using an array, each element is to hold a digit from 0 - 9, so each array index represents a 10's place.
It starts working and looping through fine, but it gets off between 13 and 21 because of the way the loop is handled. It adds the number sin the 10's place together and then saves a 31 number.
Is there a way to break out or stop it from adding those together that I'm not seeing?
num1 = [0]*100
num2 = [0]*100
num2[len(num2)-1] = 1
carry = 0
flag = True
while (flag):
#Main for loop to work through the array
for count in range (1, len(num2)):
carry = num2[len(num2) - count] + num1[len(num1) - count]
if carry > 9:
num2[len(num2)- (count + 1)] = num2[len(num2)- (count + 1)] + 1
carry = carry % 10
num1[len(num1) - count] = num2[len(num2) - count]
num2[len(num2) - count] = carry
else:
num1[len(num1) - count] = num2[len(num2) - count]
num2[len(num2) - count] = carry
print(num2)
if num2[0] != 0:
flag = False
Each time it passes the main while loop I'm hoping to see
[0,0,...,0,1]
[0,0,...,0,2]
[0,0,...,0,3]
[0,0,...,0,5]
[0,0,...,0,8]
[0,0,...,1,3]
[0,0,...,2,1]
...
but after it hits the [...,2,1] loop it moves on to [...,3,1]
Here's a bit of a cleaner version of what I believe you're trying to get at.
#Init of Fib variables
a = 0
b = 1
num = 10 #Change this to the number of fib calculation loops.
x = 0
output_arr_len = 100 #Change this to 10 for testing, as it's easier to see.
while x < num:
#Calculate Fib Sequence
c = a + b
a = b
b = c
x += 1
#Output Array
print([0] * (output_arr_len - len(str(c))) + [int(i) for i in str(c)])
Below is the output of the first 20 loops with output_arr_len set to 10.
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 3]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 5]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 8]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 3]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 3, 4]
[0, 0, 0, 0, 0, 0, 0, 0, 5, 5]
[0, 0, 0, 0, 0, 0, 0, 0, 8, 9]
[0, 0, 0, 0, 0, 0, 0, 1, 4, 4]
[0, 0, 0, 0, 0, 0, 0, 2, 3, 3]
[0, 0, 0, 0, 0, 0, 0, 3, 7, 7]
[0, 0, 0, 0, 0, 0, 0, 6, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 9, 8, 7]
[0, 0, 0, 0, 0, 0, 1, 5, 9, 7]
[0, 0, 0, 0, 0, 0, 2, 5, 8, 4]
[0, 0, 0, 0, 0, 0, 4, 1, 8, 1]
[0, 0, 0, 0, 0, 0, 6, 7, 6, 5]
[0, 0, 0, 0, 0, 1, 0, 9, 4, 6]
It was even more tricky than in my comments, but this version works correctly:
num1 = [0]*10
num2 = [0]*10
num2[len(num2)-1] = 1
sum = 0
carry = 0
flag = True
while (flag):
#Main for loop to work through the array
for count in range (1, len(num2)):
sum = num2[len(num2) - count] + num1[len(num1) - count] + carry
num1[len(num1) - count] = num2[len(num2) - count]
if sum > 9:
sum = sum % 10
carry = 1
else:
carry = 0
num2[len(num2) - count] = sum
if carry == 1:
num2[0] = num2[0] + 1
print(num2)
if num2[0] != 0:
flag = False
You have also to copy to new1 before applying the carry, even when doing it at the next higher bit...
Here's the corrections to your code. Note that Python has infinite precision integers, so I've added a Fibonacci generator to check the answer.
num1 = [0]*100
num2 = [0]*100
num2[len(num2)-1] = 1
flag = True
# Fibonacci generator for verification of answer
def fib():
a,b = 0,1
while True:
a,b = b,a+b
yield a
# Instance of the generator
f = fib()
# convert a list of single-digit integers to a real integer for display
def value(L):
assert all(n < 10 for n in L) # bug checking for invalid list values.
return int(''.join([str(i) for i in L]))
while (flag):
#Main for loop to work through the array
# Start with zero carry for first digit
carry = 0
for count in range (1,len(num2)+1): # originally off-by-1.
# compute the sum plus the carry of previous sum
temp = num2[len(num2) - count] + num1[len(num1) - count] + carry
# shift num2 digit to num1 digit
num1[len(num1) - count] = num2[len(num2) - count]
# new num2 digit is the one's place of temp sum.
num2[len(num2) - count] = temp % 10
# remember the carry (10's place) for next sum.
carry = temp // 10
# Check for bugs...compare the answer with the next Fibonacci number
assert value(num1) == next(f)
if num1[0] != 0:
flag = False
print(value(num1))
Note you can make the for loop a little simpler by remembering that negative offsets access an array from the end (num2[-1] is the last item in the array) and range can count backwards:
for count in range(-1,-len(num2)-1,-1):
temp = num2[count] + num1[count] + carry
num1[count] = num2[count]
num2[count] = temp % 10
carry = temp // 10 # remember carry for next digit

Generate unique binary permutations in python

Please, how can I get all these binary permutations, but without repetition in Python?
a = list(itertools.permutations([1, 1, 0, 0]))
for i in range(len(a)):
print a[i]
(1, 1, 0, 0)
(1, 1, 0, 0)
(1, 0, 1, 0)
...
It would be great if it would be roughly efficient since I'll have to do that with a list of even 30 elements like this.
As #Antti said in a comment, this is equivalent to looking for combinations of positions of the input list which determine which bits in the output are 1.
from itertools import combinations
def binary_permutations(lst):
for comb in combinations(range(len(lst)), lst.count(1)):
result = [0] * len(lst)
for i in comb:
result[i] = 1
yield result
for perm in binary_permutations([1, 1, 0, 0]):
print(perm)
Output:
[1, 1, 0, 0]
[1, 0, 1, 0]
[1, 0, 0, 1]
[0, 1, 1, 0]
[0, 1, 0, 1]
[0, 0, 1, 1]
Here's the algorithm from the accepted answer to the generic algorithm question, adapted into Python 3 (should work in Python 2.7+). The function generate(start, n_bits) will generate all n-bit integers starting from start lexicographically.
def generate(start, n_bits):
# no ones to permute...
if start == 0:
yield 0
return
# fastest count of 1s in the input value!!
n_ones = bin(start).count('1')
# the minimum value to wrap to when maxv is reached;
# all ones in LSB positions
minv = 2 ** n_ones - 1
# this one is just min value shifted left by number of zeroes
maxv = minv << (n_bits - n_ones)
# initialize the iteration value
v = start
while True:
yield v
# the bit permutation doesn't wrap after maxv by itself, so,
if v == maxv:
v = minv
else:
t = ((v | ((v - 1))) + 1)
v = t | (((((t & -t)) // ((v & -v))) >> 1) - 1)
# full circle yet?
if v == start:
break
for i in generate(12, 4):
print('{:04b}'.format(i))
Prints
1100
0011
0101
0110
1001
1010
If list output is generated, this can then be decorated:
def generate_list(start):
n_bits = len(start)
start_int = int(''.join(map(str, start)), 2)
# old and new-style formatting in one
binarifier = ('{:0%db}' % n_bits).format
for i in generate(start_int, n_bits):
yield [int(j) for j in binarifier(i)]
for i in generate_list([1, 1, 0, 0]):
print(i)
prints
[1, 1, 0, 0]
[0, 0, 1, 1]
[0, 1, 0, 1]
[0, 1, 1, 0]
[1, 0, 0, 1]
[1, 0, 1, 0]
What is nice about this algorithm is that you can resume it at any point. If you find a way to calculate good starting points, it is possible to parallelize too. And the numbers should be more compact than lists, so you could use them if possible.
What you are trying to do is choose two positions at which the element will be 1.
Code
from itertools import combinations
def bit_patterns(size, ones):
for pos in map(set, combinations(range(size), ones)):
yield [int(i in pos) for i in range(size)]
Output
>>> print(*bit_patterns(4, 2), sep='\n')
[1, 1, 0, 0]
[1, 0, 1, 0]
[1, 0, 0, 1]
[0, 1, 1, 0]
[0, 1, 0, 1]
[0, 0, 1, 1]
Alternative
A fun alternative is to see the desired output as the binary representations which have only two ones. We can use this definition to get the output you want.
from itertools import combinations
def bit_patterns(size, ones):
for t in combinations([1 << i for i in range(size)], ones):
yield [int(n) for n in f'{sum(t):0{size}b}']
Here is a recursive solution:
def bin_combs_iter(ones, zeros):
if not zeros:
yield [1] * ones
elif not ones:
yield [0] * zeros
else:
for x in bin_combs_iter(ones - 1, zeros):
x.append(1)
yield x
for x in bin_combs_iter(ones, zeros - 1):
x.append(0)
yield x
def bin_combs(ones, zeros):
return list(bin_combs_iter(ones, zeros))

Count number of tails since the last head

Consider a sequence of coin tosses: 1, 0, 0, 1, 0, 1 where tail = 0 and head = 1.
The desired output is the sequence: 0, 1, 2, 0, 1, 0
Each element of the output sequence counts the number of tails since the last head.
I have tried a naive method:
def timer(seq):
if seq[0] == 1: time = [0]
if seq[0] == 0: time = [1]
for x in seq[1:]:
if x == 0: time.append(time[-1] + 1)
if x == 1: time.append(0)
return time
Question: Is there a better method?
Using NumPy:
import numpy as np
seq = np.array([1,0,0,1,0,1,0,0,0,0,1,0])
arr = np.arange(len(seq))
result = arr - np.maximum.accumulate(arr * seq)
print(result)
yields
[0 1 2 0 1 0 1 2 3 4 0 1]
Why arr - np.maximum.accumulate(arr * seq)? The desired output seemed related to a simple progression of integers:
arr = np.arange(len(seq))
So the natural question is, if seq = np.array([1, 0, 0, 1, 0, 1]) and the expected result is expected = np.array([0, 1, 2, 0, 1, 0]), then what value of x makes
arr + x = expected
Since
In [220]: expected - arr
Out[220]: array([ 0, 0, 0, -3, -3, -5])
it looks like x should be the cumulative max of arr * seq:
In [234]: arr * seq
Out[234]: array([0, 0, 0, 3, 0, 5])
In [235]: np.maximum.accumulate(arr * seq)
Out[235]: array([0, 0, 0, 3, 3, 5])
Step 1: Invert l:
In [311]: l = [1, 0, 0, 1, 0, 1]
In [312]: out = [int(not i) for i in l]; out
Out[312]: [0, 1, 1, 0, 1, 0]
Step 2: List comp; add previous value to current value if current value is 1.
In [319]: [out[0]] + [x + y if y else y for x, y in zip(out[:-1], out[1:])]
Out[319]: [0, 1, 2, 0, 1, 0]
This gets rid of windy ifs by zipping adjacent elements.
Using itertools.accumulate:
>>> a = [1, 0, 0, 1, 0, 1]
>>> b = [1 - x for x in a]
>>> list(accumulate(b, lambda total,e: total+1 if e==1 else 0))
[0, 1, 2, 0, 1, 0]
accumulate is only defined in Python 3. There's the equivalent Python code in the above documentation, though, if you want to use it in Python 2.
It's required to invert a because the first element returned by accumulate is the first list element, independently from the accumulator function:
>>> list(accumulate(a, lambda total,e: 0))
[1, 0, 0, 0, 0, 0]
The required output is an array with the same length as the input and none of the values are equal to the input. Therefore, the algorithm must be at least O(n) to form the new output array. Furthermore for this specific problem, you would also need to scan all the values for the input array. All these operations are O(n) and it will not get any more efficient. Constants may differ but your method is already in O(n) and will not go any lower.
Using reduce:
time = reduce(lambda l, r: l + [(l[-1]+1)*(not r)], seq, [0])[1:]
I try to be clear in the following code and differ from the original in using an explicit accumulator.
>>> s = [1,0,0,1,0,1,0,0,0,0,1,0]
>>> def zero_run_length_or_zero(seq):
"Return the run length of zeroes so far in the sequnece or zero"
accumulator, answer = 0, []
for item in seq:
accumulator = 0 if item == 1 else accumulator + 1
answer.append(accumulator)
return answer
>>> zero_run_length_or_zero(s)
[0, 1, 2, 0, 1, 0, 1, 2, 3, 4, 0, 1]
>>>

Need to generate a 2D python list with each column having 2 possibilities, for each row

I need to generate a two-dimensional python list. It would consist of 10 columns, with each column value being either '1' or '0'. Given these conditions, my list needs to be an exhaustive list of all the combinations that can be formed in this way. It'd naturally end up being 1024 rows long (2^10). However, I have no clue where to get started on this. Can anyone help?
So this is how I worked through this problem. First I saw that we wanted to loop over all 1024 combinations of 0s and 1s. This is essentially counting from 0 to 1023 in binary. So I made a for loop from 0 to 1023 and at each iteration, I converted the iteration variable i into binary with format(i, 'b') and then turned it into a list with the list method. In the case of a number like 1, this gets converted into ['1'] but we want to convert that into ['0', '0', '0', '0', '0', '0', '0', '0', '0', '1'] which is what line
4 does. Finally, we append each result into the 'table' variable.
table=[]
for i in range(1024):
binaryRepresentation = list(format(i, 'b'))
finalRepresentation = ['0']*(10-len(binaryRepresentation)) + binaryRepresentation
table.append(finalRepresentation)
You can use combinations from itertools module, that can create a list of tuples, not a list of lists:
from itertools import combinations
# Generate all the combinations of 0 and 1
# in a list of tuples where each tuple is formed by 10 elements
# Which leads to 184756 combinations
gen_list = combinations([0,1]*10, 10)
# remove duplicates
unique_elements = list(set(gen_list))
# len(unique_elements)
# >>> 1024
An overview of the created list:
>>> unique_elements
[
(0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
(0, 1, 0, 1, 0, 1, 0, 1, 0, 0)
...
(1, 1, 1, 0, 1, 0, 0, 1, 1, 1)
]
You should use numpy for this. For array creation, you could do:
import numpy as np
rows, cols = 1024, 10
arr = np.zeros((rows, cols))
Now, for setting certain values to 1 based on your condition, this could be used:
# this should be changed based on your needs
arr[arr > 0] = 1 # set all values greater than 0 to 1
If you need to create an array initialized with random binary data, you could do:
arr = np.random.randint(2, size=(rows,cols))
If performance isn't a concern, you could always count from 0 to 1023, create the string representation of that number in base 2 then convert to a list.
def binary_cols(n_cols):
for i in range(2**n_cols):
k = [int(j) for j in "{:b}".format(i)]
k = [0]*(n_cols - len(k)) + k
yield k
for col in binary_cols(10):
print col
gives
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
...
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
print(len(list(binary_cols(10))))
1024
edit: I've just noticed that my answer is essentially a duplicate of Saleh Hindi's. Leaving mine here as there is a big enough difference in the specific tools used for the task, but their answer has a better explanation.

How to extract the bits of larger numeric Numpy data types

Numpy has a library function, np.unpackbits, which will unpack a uint8 into a bit vector of length 8. Is there a correspondingly fast way to unpack larger numeric types? E.g. uint16 or uint32. I am working on a question that involves frequent translation between numbers, for array indexing, and their bit vector representations, and the bottleneck is our pack and unpack functions.
You can do this with view and unpackbits
Input:
unpackbits(arange(2, dtype=uint16).view(uint8))
Output:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
For a = arange(int(1e6), dtype=uint16) this is pretty fast at around 7 ms on my machine
%%timeit
unpackbits(a.view(uint8))
100 loops, best of 3: 7.03 ms per loop
As for endianness, you'll have to look at http://docs.scipy.org/doc/numpy/user/basics.byteswapping.html and apply the suggestions there depending on your needs.
This is the solution I use:
def unpackbits(x, num_bits):
if np.issubdtype(x.dtype, np.floating):
raise ValueError("numpy data type needs to be int-like")
xshape = list(x.shape)
x = x.reshape([-1, 1])
mask = 2**np.arange(num_bits, dtype=x.dtype).reshape([1, num_bits])
return (x & mask).astype(bool).astype(int).reshape(xshape + [num_bits])
This is a completely vectorized solution that works with any dimension ndarray and can unpack however many bits you want.
I have not found any function for this too, but maybe using Python's builtin struct.unpack can help make the custom function faster than shifting and anding longer uint (note that I am using uint64).
>>> import struct
>>> N = np.uint64(2 + 2**10 + 2**18 + 2**26)
>>> struct.unpack('>BBBBBBBB', N)
(2, 4, 4, 4, 0, 0, 0, 0)
The idea is to convert those to uint8, use unpackbits, concatenate the result. Or, depending on your application, it may be more convenient to use structured arrays.
There is also built-in bin() function, which produces string of 0s and 1s, but I am not sure how fast it is and it requires postprocessing too.
This works for arbitrary arrays of arbitrary uint (i.e. also for multidimensional arrays and also for numbers larger than the uint8 max value).
It cycles over the number of bits, rather than over the number of array elements, so it is reasonably fast.
def my_ManyParallel_uint2bits(in_intAr,Nbits):
''' convert (numpyarray of uint => array of Nbits bits) for many bits in parallel'''
inSize_T= in_intAr.shape
in_intAr_flat=in_intAr.flatten()
out_NbitAr= numpy.zeros((len(in_intAr_flat),Nbits))
for iBits in xrange(Nbits):
out_NbitAr[:,iBits]= (in_intAr_flat>>iBits)&1
out_NbitAr= out_NbitAr.reshape(inSize_T+(Nbits,))
return out_NbitAr
A=numpy.arange(256,261).astype('uint16')
# array([256, 257, 258, 259, 260], dtype=uint16)
B=my_ManyParallel_uint2bits(A,16).astype('uint16')
# array([[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
# [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
# [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
# [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]], dtype=uint16)

Categories