2

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
  • The use of flipud looks funny. You should be able write the numpy power line much like matlab one, taking advantage of broadcasting to produce a 2d array. Commented Jun 9, 2017 at 4:37
  • @hpaulj the problem is that when I try to use integer input x python doesn't convert it into a list like [x], and arrays change into list of lists like [[x,y]] for [x,y] when I manually convert it. I guess I need to get [x] for x and [[x],[y]] for [x,y], but I do not know how to manage this easy step with few lines of codes as in matlab. Commented Jun 9, 2017 at 4:59

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

3 Comments

Do we really need a loop? Isn't there a direct way that numpy can handle this without any loops?
I'm not 100% positive on that, since we are still relying on scalar-array multiplication. Maybe if you can turn the operation to an array-array multiplication (np.dot()) ? Perhaps with an identity matrix instead of ones, but I'm not sure about the math on that one.
Thanks for the answer. I guess there is a direct method to get same operation without going into loops as we do in matlab. I have just started to learn python, and trying to deal with basics. I hope we will see other answers as well for shortcuts. (I am sorry that I am not able to give you +1 since I don't have enough reputation yet)
0

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 Comments

Thanks for the answer. It works for d = [13,15], but gives IndexError when d is assigned to an integer directly as d = 13 even after using d=np.atleast_1d(d). In MATLAB it automatically converts an integer x into array [x], so no problems occur during operations.
I have commented without seeing your edit regarding to np.floor((d[...,None]%(2*power))/power. It now works with 0d arrays as well. But outputs are in different formats. This will work for forward operation, but will not be handy for inverse function. Can I simply add my solution as well into your answer by editing and then accept your answer?
The atleast_1d should work with scalars. Keep in mind that MATLAB doesn't have scalars; everything is 2d. Your 1 row MATLAB case has shape (1,8), where as in numpy it could be (8,).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.