0

i have a 1-d array of 1's and 0's in a numpy integer array, i want to pack these values in a array of unsigned 32 bit integer values.

for example, lets say the integer array is

{0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1

i want to convert it to this

{0b01111111111000000000000111111111,0b11111111111111110000111111111111}

how can i achieve this ? thanks in advance

  • Does this answer your question? [Fastest way to convert a binary list(or array) into an integer in Python](https://stackoverflow.com/questions/24560596/fastest-way-to-convert-a-binary-listor-array-into-an-integer-in-python) – mcsoini Nov 07 '21 at 12:23

3 Answers3

2

You use bitshift to move the digit to the correct binary index. Then just accumulate the values.

(d << np.arange(len(d))).sum()

Here a more extensive version:

# first, extend to a multiple of 32
d = np.append(d, np.zeros(len(d) & 31, dtype=d.dtype))
# reshape into Nx32
d = d.reshape((-1, 32))
# broadcasted bitshift
bits = d << np.arange(32, dtype=d.dtype))
# accumulate into one value per row
bits = bits.sum(axis=1)
Homer512
  • 9,144
  • 2
  • 8
  • 25
1

I would use numpy.packbits and numpy.frombuffer. Result is missing first zero though, but mcsoini says it is expected though - the zero is there, just is not printed.

import numpy as np

data = [0,1,1,1,1,1,1,1,1,1,
        1,0,0,0,0,0,0,0,0,0,
        0,0,0,1,1,1,1,1,1,1,
        1,1,1,1,1,1,1,1,1,1,
        1,1,1,1,1,1,1,1,0,0,
        0,0,1,1,1,1,1,1,1,1,
        1,1,1]

result = np.frombuffer(np.packbits(data).tobytes(), dtype=np.uint32)
print([bin(item) for item in result])
['0b11111111000000011110000001111111', '0b11111110000011111111111111111111']
dankal444
  • 3,172
  • 1
  • 23
  • 35
0

I think your best bet is to go through strings:

d = [0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1, 0]

[bin(int("".join(map(str, integer)), 2)) 
 for integer in np.array_split(d, len(d) / 32)]

# Out:
# ['0b1111111111000000000000111111111', '0b11111111111111110000111111111110']

I added a zero to the input data to make the length a multiple of 32.

mcsoini
  • 6,280
  • 2
  • 15
  • 38