Compute the product of the next n elements in an array

I would like to calculate the product of the following nadjacent matrix elements. The number of nelements to be multiplied must be indicated in the functional input. For example, for this input, I must calculate the product every 3 consecutive elements, starting from the first.

[p, ind] = max_product([1 2 2 1 3 1],3);

It gives [1*2*2, 2*2*1, 2*1*3, 1*3*1] = [4,4,6,3].

Is there a practical way to do this? Now I do this using:

for ii = 1:(length(v)-2)
    p = prod(v(ii:ii+n-1));
end

where vis the input vector, and nis the number of elements to be multiplied.

in this example n=3, but can take any positive integer value.

Depending on whether it is nodd or even or length(v)odd or even, sometimes I get the right answers, but sometimes an error.
For example, for arguments:

v = [1.35912281237829 -0.958120385352704 -0.553335935098461 1.44601450110386 1.43760259196739 0.0266423803393867 0.417039432979809 1.14033971399183 -0.418125096873537 -1.99362640306847 -0.589833539347417 -0.218969651537063 1.49863539349242 0.338844452879616 1.34169199365703 0.181185490389383 0.102817336496793 0.104835620599133 -2.70026800170358 1.46129128974515 0.64413523430416 0.921962619821458 0.568712984110933] 
n = 7

I get an error message:

Index exceeds matrix dimensions.
Error in max_product (line 6)  
p = prod(v(ii:ii+n-1));

Is there a proper general way to do this?

+4
source share
6 answers

Update

Inspired by the well-crafted Dev-iL answer , this is a handy solution that doesn't require Matlab R2016a or higher.

out = real( exp(conv(log(a),ones(1,n),'valid')) )

The main idea is to convert the multiplication into a sum and use a moving average, which, in turn, can be implemented by olution. conv


gallery :

a = [1 2 2 1 3 1]
n = 3

%// circulant matrix
tmp = gallery('circul', a(:))
%// product of relevant parts of matrix
out = prod(tmp(end-n+1:-1:1, end-n+1:end), 2)

out =

     4
     4
     6
     3

:

a = [10 9 8 7 6 5 4 3 2 1]
n = 2

%// cumulative product
x = [1 cumprod(a)] 
%// shifted by n and divided by itself
y = circshift( x,[0 -n] )./x 
%// remove last elements 
out = y(1:end-n) 

out =

    90    72    56    42    30    20    12     6     2
+5

numpy roll_product MATLAB, movsum, R2016a.

, :

enter image description here

MATLAB :

function P = movprod(vec,window_sz)
  P = exp(movsum(log(vec),[0 window_sz-1],'Endpoints','discard'));
  if isreal(vec)   % Ensures correct outputs when the input contains negative and/or
    P = real(P);   %   complex entries.
  end
end

:

  • , .
  • , / / .
  • , ( ) , movsum.
  • 1 st double, complex double row.
  • .
+7

. for for ii = 1:(length(v)-n+1), .

, gallery, @thewaywewalk answer.

+2

, . , for ii = 1:(length(v)-2), ii.

:

function out = max_product(in,size)
    size = size-1;                 % this is because we add size to i later
    out = zeros(length(in),1)      % assuming that this is a column vector
    for i = 1:length(in)-size
        out(i) = prod(in(i:i+size));
    end

, :

for ii = 1:(length(v)-(n-1))
    p = prod(v(ii:ii+(n-1)));
end

.

+2

bsxfun, , 3 , . , :

max_product = @(v, n) prod(v(bsxfun(@plus, (1 : n), (0 : numel(v)-n)')), 2);
p = max_product([1 2 2 1 3 1],3)

: , , @Dev-iL, , fftconv, Octave conv

+1

If you can upgrade to R2017a, you can use the new movprod function to calculate the window product.

+1
source

Source: https://habr.com/ru/post/1653593/


All Articles