Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert binary (0|1) numpy to integer or binary-string?

Is there a shortcut to Convert binary (0|1) numpy array to integer or binary-string ? F.e.

b = np.array([0,0,0,0,0,1,0,1])   
  => b is 5

np.packbits(b)

works but only for 8 bit values ..if the numpy is 9 or more elements it generates 2 or more 8bit values. Another option would be to return a string of 0|1 ...

What I currently do is :

    ba = bitarray()
    ba.pack(b.astype(np.bool).tostring())
    #convert from bitarray 0|1 to integer
    result = int( ba.to01(), 2 )

which is ugly !!!

like image 668
sten Avatar asked Dec 09 '16 22:12

sten


People also ask

How to convert an integer to a binary string in Python?

This tutorial will teach you how to use the os and pathlib libraries to do just that! The Python bin () function is short for binary and allows us to convert an integer to a binary string, which is prefixed by '0b'. In later section, you’ll learn how to convert the integer using Python without the prefix.

How do you find a non integer number in binary?

Solution: First, let’s start off by asking ourselves what a non-integer number in binary looks like. By analogy to a decimal number, the binary number 0 .101 2 would look like: 0. 101 2 = 1 * 1/2 1 + 0 *1/2 2 + 1 * 1/2 3 .

How do you convert binary numbers to decimal numbers?

By analogy to a decimal number, the binary number 0 .101 2 would look like: 0. 101 2 = 1 * 1/2 1 + 0 *1/2 2 + 1 * 1/2 3 . To print the decimal part, we can multiply by 2 and check if 2*n is greater than or equal to 1. This is essentially “shifting” the fractional sum. That is: If r >= 1, then we know that n had a 1 right after the decimal point.

What is the binary number 0 101 2?

By analogy to a decimal number, the binary number 0 .101 2 would look like: 0. 101 2 = 1 * 1/2 1 + 0 *1/2 2 + 1 * 1/2 3 .


2 Answers

One way would be using dot-product with 2-powered range array -

b.dot(2**np.arange(b.size)[::-1])

Sample run -

In [95]: b = np.array([1,0,1,0,0,0,0,0,1,0,1])

In [96]: b.dot(2**np.arange(b.size)[::-1])
Out[96]: 1285

Alternatively, we could use bitwise left-shift operator to create the range array and thus get the desired output, like so -

b.dot(1 << np.arange(b.size)[::-1])

If timings are of interest -

In [148]: b = np.random.randint(0,2,(50))

In [149]: %timeit b.dot(2**np.arange(b.size)[::-1])
100000 loops, best of 3: 13.1 µs per loop

In [150]: %timeit b.dot(1 << np.arange(b.size)[::-1])
100000 loops, best of 3: 7.92 µs per loop

Reverse process

To retrieve back the binary array, use np.binary_repr alongwith np.fromstring -

In [96]: b = np.array([1,0,1,0,0,0,0,0,1,0,1])

In [97]: num = b.dot(2**np.arange(b.size)[::-1]) # integer

In [98]: np.fromstring(np.binary_repr(num), dtype='S1').astype(int)
Out[98]: array([1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1])
like image 73
Divakar Avatar answered Sep 20 '22 19:09

Divakar


My timeit results:

b.dot(2**np.arange(b.size)[::-1])
100000 loops, best of 3: 2.48 usec per loop

b.dot(1 << np.arange(b.size)[::-1])
100000 loops, best of 3: 2.24 usec per loop

# Precompute powers-of-2 array with a = 1 << np.arange(b.size)[::-1]
b.dot(a)
100000 loops, best of 3: 0.553 usec per loop

# using gmpy2 is slower
gmpy2.pack(list(map(int,b[::-1])), 1)
100000 loops, best of 3: 10.6 usec per loop

So if you know the size ahead of time, it's significantly faster to precompute the powers-of-2 array. But if possible, you should do all computations simultaneously using matrix multiplication like in Geoffrey Anderson's answer.

like image 40
qwr Avatar answered Sep 20 '22 19:09

qwr