我想计算矩阵的下一个n
相邻元素的乘积。要乘以的元素的数量n
应在函数的输入中给出。
例如,对于这个输入,我应该从第一个开始计算每3个连续元素的乘积。
[p, ind] = max_product([1 2 2 1 3 1],3);
这会给[1*2*2, 2*2*1, 2*1*3, 1*3*1] = [4,4,6,3]
。
有没有实用的方法呢?现在我使用:
for ii = 1:(length(v)-2)
p = prod(v(ii:ii+n-1));
end
其中v
是输入向量,n
是要乘的元素数。
在此示例n=3
中,但可以采用任何正整数值。
根据n
是奇数还是偶数或length(v)
是奇数还是偶数,我有时得到正确答案,但有时会出错。
例如参数:
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
我收到错误:
Index exceeds matrix dimensions.
Error in max_product (line 6)
p = prod(v(ii:ii+n-1));
有没有正确的一般方法呢?
答案 0 :(得分:7)
根据Fast numpy rolling_product中的解决方案,我想建议一个MATLAB版本,它利用 R2016a 中引入的movsum
函数。
数学推理是数字的乘积等于其对数之和的指数:
上述可能的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
提供的任何其他自定义。double
或complex double
行向量。答案 1 :(得分:5)
受到精心设计的answer of Dev-iL的启发,这个方便的解决方案不需要 Matlab R2016a或更高版本:
out = real( exp(conv(log(a),ones(1,n),'valid')) )
基本思想是将乘法转换为和,并且可以使用移动平均值,而这可以通过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
答案 2 :(得分:2)
你的方法是正确的。您应该将for循环更改为for ii = 1:(length(v)-n+1)
,然后它才能正常工作。
如果您不打算处理大量输入,则另一种方法是使用gallery
@thewaywewalk's answer中所述的FileStream stream=File.OpenRead(@"D:\FileDownLoad\DeskTop\1.txt");
MemoryStream MS=new MemoryStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(MS);
zipOutputStream.SetLevel(9);
ZipEntry entry = new ZipEntry("1.txt");
zipOutputStream.PutNextEntry(entry);
byte[] buffer = new byte[stream.Length];
int byteRead = 0;
while ((byteRead = stream.Read(buffer, 0, buffer.Length)) > 0)
zipOutputStream.Write(buffer, 0, byteRead);
zipOutputStream.IsStreamOwner = false;
stream.Close();
zipOutputStream.Close();
MS.Position = 0;
Response.ContentType = "application/application/octet-stream";
Response.AppendHeader("content-disposition", "attachment; filename=\"Download.zip\"");
Response.BinaryWrite(MS.ToArray());
。
答案 3 :(得分: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
这应该照顾索引问题。
答案 4 :(得分:1)
使用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
答案 5 :(得分:1)
如果您可以升级到R2017a,则可以使用新的movprod功能计算窗口产品。