using numpy arrays for integer and array inputs

I am a Matlab user, and trying to move into Python. I tried to code a minimal example of de2bi function (which converts a decimal into binary as right-msb) in Python which I had before in Matlab. But, I am confused with numpy arrays.

Python code:

import numpy as np def de2bi(d, n) d = np.array(d) power = 2**np.arange(n) d = d * np.ones((1,n)) b = np.floor((d%(2*power))/power) return b 

Python output:

>>> print(de2bi(13,8)) [[ 1. 0. 1. 1. 0. 0. 0. 0.]] print(de2bi([13,15],8)) #This line fails 

Matlab code:

function b = d2b( d, n ) d = d(:); power = ones(length(d), 1)*(2.^(0 : n-1)); d = d * ones(1, n); b = floor(rem(d, 2*power)./power); end 

Matlab output:

>> d2b(13,8) ans = 1 0 1 1 0 0 0 0 >> d2b([13,15],8) ans = 1 0 1 1 0 0 0 0 1 1 1 1 0 0 0 0 

Matlab code is working both for integer inputs and array of integers. But python code works for integer inputs, but keeps failing for arrays. How to manage operations both for integers and integer arrays in Python automatically? It may be a very easy question, excuse me, but I am a very newbie in python.

Thanks in advance.

2

2 Answers

Your problem is with the multiplication: d = d * np.ones((1,n)). NumPy attemps to perform an element-wise multiplication, which would fail because of dimension mismatch (your ones array has only one row). When d is scalar though, NumPy can infer that you mean multiply to scalar, hence the code would run.

What you really want to do (as I understand) is to expand each element to an n-length row. A possible solution would be to create an intermediate array to hold the new values, since the size of an array is not changeable:

def d2b(d, n): d = np.array(d) d = np.reshape(d, (1, -1)) power = np.flipud(2**np.arange(n)) g = np.zeros((np.shape(d)[1], n)) for i, num in enumerate(d[0]): g[i] = num * np.ones((1,n)) b = np.floor((g%(2*power))/power) return b 
3

Does this help?

In [439]: d=np.array([13,15]) In [440]: power=np.ones((d.shape[0],1))*(2**np.arange(8)) In [441]: power Out[441]: array([[ 1., 2., 4., 8., 16., 32., 64., 128.], [ 1., 2., 4., 8., 16., 32., 64., 128.]]) In [442]: np.floor((d[:,None]%(2*power))/power) Out[442]: array([[ 1., 0., 1., 1., 0., 0., 0., 0.], [ 1., 1., 1., 1., 0., 0., 0., 0.]]) 

we don't even need the ones:

In [443]: power = 2**np.arange(8) In [444]: np.floor((d[:,None]%(2*power))/power) Out[444]: array([[ 1., 0., 1., 1., 0., 0., 0., 0.], [ 1., 1., 1., 1., 0., 0., 0., 0.]]) 

When broadcasting d against power, the dimension expansion for power is automatic: d[:,None]%(2*power[None,:]). The ones in MATLAB accomplish the same dimension expansion (to (2,8) shaped arrays).

May want to start with d=np.atleast_1d(d), so it treats the scalar case like a 1 element array. We could refine things so it returns a 1d array when given a scalar, and 2d when given a list or 1d array. In MATLAB everything is 2d or higher.


Better yet, use ellipsis when expanding d. Then d can be 0d, 1d, or even nd.

np.floor((d[...,None]%(2*power))/power) 
3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like