Elements processing in array

10 Ansichten (letzte 30 Tage)
Lee Lee
Lee Lee am 10 Apr. 2017
Bearbeitet: Jan am 11 Apr. 2017
If array A=[ b c ], I want to create value [b+c -b+c b-c -b-c]
or A=[ b c d ], then output should be [ b+c+d b+c-d b-c+d b-c-d -b+c+d -b+c-d -b-c+d -b-c-d ]
Is there any function in MATLAB that can easily solve my problem ? Thanks.

Akzeptierte Antwort

Guillaume
Guillaume am 10 Apr. 2017
You basically want the sum of the n-ary product of the +/- sets of each element of your array. That can be done easily with ndgrid:
A = [1 3 8 2]; %demo data;
sets = num2cell([A; -A], 1); %split into sets of +/- values
nprod = cell(1, numel(A)); %create destination for n-ary product
[nprod{:}] = ndgrid(sets{:}); %calculate n-ary product
nprod = reshape(cat(numel(A)+1, nprod{:}), [], numel(A)); %concatenate into one matrix and reshape. Each row is one of the possible combination
sumnprod = sum(nprod, 2) %wanted result
  2 Kommentare
Lee Lee
Lee Lee am 10 Apr. 2017
OK,thanks a lot.
Jan
Jan am 11 Apr. 2017
+1: This is efficient for larg inputs - and as usual for code concerning permutations, "large" means 20 elements already.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Jan
Jan am 11 Apr. 2017
Bearbeitet: Jan am 11 Apr. 2017
n = numel(A);
M = VChooseKRO([-1, 1], n) * A(:);
Timings: See comment.
And if single precision is enough, this is 33% faster for an [1 x 20] input:
n = numel(A);
M = VChooseKRO(single([-1, 1]), n) * A(:);

Jan
Jan am 10 Apr. 2017
Bearbeitet: Jan am 11 Apr. 2017
n = numel(A);
M = (1 - 2 * (dec2bin(0:2^n-1) - '0')) * A(:);
[EDITED, parenthesis inserted]
  2 Kommentare
Guillaume
Guillaume am 11 Apr. 2017
That is indeed shorter than my answer and possibly will fall over later than ndgrid on larger arrays. However, it's probably slower due to number - string conversions.
Jan
Jan am 11 Apr. 2017
Bearbeitet: Jan am 11 Apr. 2017
@Guillaume: I know, I detest dec2bin in my code and use it in the forum only. I productive codes I'd use:
n = numel(A);
s = rem(floor((0:2^n-1).' * pow2((1-n):0)), 2);
M = (1 - 2 * s) * A(:));
Before speculating about speed, let's measure it:
A = 1:5;
rep = 10000; % Repetitions for accurate timings
tic;
for k = 1:rep
sets = num2cell([A; -A], 1);
nprod = cell(1, numel(A));
[nprod{:}] = ndgrid(sets{:});
nprod = reshape(cat(numel(A)+1, nprod{:}), [], numel(A));
sumnprod = sum(nprod, 2);
end
toc
tic;
for k = 1:rep
n = numel(A);
M = (1 - 2 * (dec2bin(0:2^n-1) - '0')) * A(:);
end
toc
tic;
for k = 1:rep
n = numel(A);
s = rem(floor((0:2^n-1).' * pow2((1-n):0)), 2);
M = (1 - 2 * s) * A(:);
end
toc
tic;
for k = 1:rep
M = VChooseKRO([-1, 1], numel(A)) * A(:);
end
toc
R2016b/64, Win7:
Elapsed time is 1.799392 seconds. Guillaume
Elapsed time is 0.355071 seconds. DEC2BIN
Elapsed time is 0.278210 seconds. my_DEC2BIN
Elapsed time is 0.078271 seconds. VChooseKRO
And now with a larger input:
A = 1:20;
rep = 2;
Elapsed time is 1.007342 seconds. Guillaume
Elapsed time is 3.261605 seconds. DEC2BIN
Elapsed time is 2.929411 seconds. my_DEC2BIN
Elapsed time is 0.468315 seconds. VChooseKRO
Conclusion: The multiplication with the binary matrix is fast for small arrays and slow for large arrays. The conversion to CHAR and back has some overhead. Creating large temporary array in a DEC2BIN style is a bad idea. But with an efficient creation of the [1, -1] matrix the computations are faster than the cell approach. But therefore it is required to compile a C-Mex function. Therefore is pure Matlab is wanted, Guillaume's method is better - except a user needs millions of results for short input vectors.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Linear Algebra finden Sie in Help Center und File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by