Converting binary like table but using decimal values

Kyle Young (view profile)

on 6 May 2019
Latest activity Edited by Stephen Cobeldick

on 7 May 2019

Stephen Cobeldick (view profile)

I'm trying to create a table that will start at a negative value and increment by one in the right most column and each column to the left will only increment when there is a carry. This is similar to a binary table or any other base-n table, but I would like to keep the values in decimal format, not alpha-numeric.
I had this code which was working well, but fails if I make 'n' > 5 due to the alpha-numerics once the decimal value reaches '10'.
m = 3; %Number of signals
n = n+1; %Number of harmonics
%% Harmonic Basis Matrix
T = zeros((2*n-1)^m,m);
for k = 1:(2*n-1)^m
T(k,:) = dec2base(k-1,2*n-1,m)-num2str(n-1);
end
When I subtract num2str(n-1) from the string '00A', the result is double('00A') = 17 - double('0') = 5 ==> 17-5 = 12.
I thought about creating the matrix in alpha-numeric string form and just splitting the values into columns, but couldn't figure out how to do that effectively without using cells - which I need to avoid as this will be used in some matrix algebra.
Please note, that the variables 'm' and 'n' are part of a function input and could be completely arbitrary.
Thanks for the help!

Stephen Cobeldick

Stephen Cobeldick (view profile)

on 7 May 2019
>> [X,Y] = meshgrid(-2:2);
>> M = [X(:),Y(:)]
M =
-2 -2
-2 -1
-2 0
-2 1
-2 2
-1 -2
-1 -1
-1 0
-1 1
-1 2
0 -2
0 -1
0 0
0 1
0 2
1 -2
1 -1
1 0
1 1
1 2
2 -2
2 -1
2 0
2 1
2 2
Jan

Jan (view profile)

on 7 May 2019
m and n can be arbitrary. Then ndgrid is needed.
Kyle Young

Kyle Young (view profile)

on 7 May 2019
Meshgrid/ndgrid is definitely more simple, but how would you handle when m > 2?
Using the grid method, there needs to be an output stored for each level of 'm'.
I.e. for m = 2
[x,y] = ndgrid(-2:2);
T = [y(:),x(:)]
but for m = 4
[x,y,z,k] = ndgrid(-2:2);
T = [k(:),z(:),y(:),x(:)]
The number of outputs would change for every different 'm' value. Is this adaptable in Matlab?
Thanks

R2019a

Stephen Cobeldick (view profile)

on 7 May 2019
Edited by Stephen Cobeldick

Stephen Cobeldick (view profile)

on 7 May 2019

You can use comma-separated lists on the output of ndgrid:
>> m = 4;
>> C = cell(1,m);
>> [C{:}] = ndgrid(-2:2);
>> C = cellfun(@(a)a(:),C,'uni',0);
>> T = [C{end:-1:1}]
ans =
-2 -2 -2 -2
-2 -2 -2 -1
-2 -2 -2 0
-2 -2 -2 1
-2 -2 -2 2
-2 -2 -1 -2
-2 -2 -1 -1
-2 -2 -1 0
-2 -2 -1 1
-2 -2 -1 2
-2 -2 0 -2
-2 -2 0 -1
-2 -2 0 0
-2 -2 0 1
-2 -2 0 2
... lots of lines here
2 2 1 1
2 2 1 2
2 2 2 -2
2 2 2 -1
2 2 2 0
2 2 2 1
2 2 2 2

Kyle Young

Kyle Young (view profile)

on 7 May 2019
Great tutorial on comma separated lists. I didn't realize that was even an option for input/outputs. This will be very usefull forever more.
I'll need to read up on the cellfun(@(a)...) line, but this defintely works. Thanks, Stephen.
Stephen Cobeldick

Stephen Cobeldick (view profile)

on 7 May 2019
"Great tutorial on comma separated lists..."
Thank you, you can vote for it too, if you liked it :) Comma-separated lists are certainly very handy and well worth learning about.
"I'll need to read up on the cellfun(@(a)...) line..."
All that does lines does is convert the content of each cell (i.e. the array output from ndgrid) into a column vector. An explicit loop would likely be a tad faster, in case speed is of major concern.

Walter Roberson (view profile)

on 6 May 2019

ndgrid or meshgrid and reshape to column vectors and put the columns together.

on 7 May 2019
Edited by Jan

Jan (view profile)

on 7 May 2019

R = VChooseKRO(-2:2, 2)
Or:
n = 2;
m = 2;
len = (2*n+1)^m; % Not: (2*n-1)^m !
T = zeros(len, m);
v = repmat(-n, 1, m);
for k = 1:len
T(k, :) = v;
for im = m:-1:1
if v(im) < n
v(im) = v(im) + 1;
break;
end
v(im) = -n;
end
end
Or:
len = (2*n+1)^m; % Not: (2*n-1)^m !
T = zeros(len, m);
v = (-n:n).';
nv = numel(v);
r1 = nv ^ (m - 1);
r2 = 1;
for k = 1:m
T(:, k) = repmat(repelem(v, r1, 1), r2, 1);
r1 = r1 / nv;
r2 = r2 * nv;
end