我有2个长度为n的向量,第一个由整数组成,第二个由0到1之间的实数组成.Es:
a = [6 2 5 3] and b = [0.1 0.2 0.04 1]
我首先需要复制第二个向量的值a与第一个向量a(行方向)的数量一样多次:例如,对于第一个元素,我需要6个值为0.1的行,而不是第二个2个其他行,值为0.2,依此类推填充所有向量。生成的向量将如下所示:
B = [0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.04 0.04 0.04 0.04 0.04 1 1 1]
我在for循环(每行)中使用了repmat来获得此结果。问题是矢量很快就会变得太大而且很快就会卡住,因为我正在使用大数字。所以,我试图将每个新的'repmat vector'存储在具有预定行数r的矩阵中(我需要r相对较高)并使用带有pad = NaN的vec2mat来调整维度。这种方法效果很好但仍然要填充的矩阵大小很高,并且在给定点处循环卡住。我还尝试将每个新的'repmat vector'存储在数组中。这种方法运行良好且非常快,最终结果是一个包含n个单元格的数组,每个单元格包含不同长度的向量。在上面的例子中,我将得到一个数组c 1x4,在第一个单元格中有向量[0.1 0.1 0.1 0.1 0.1 0.1],在第二个单元中有向量[0.2 0.2],依此类推。
在这个阶段有我的问题。修正一个整数r,我需要计算一个求和序列,对按顺序取得的单元格中所有值的值求和(每个r元素)。这意味着,我需要获取第一个单元格的第一个r值,而不是继续第一个集合之后的第二组r值的总和。当第一个单元的矢量完成时,它应该从第二个单元开始,直到阵列的最后一个单元。问题是r可能高于或低于阵列的每个单元中不同向量的长度。例如,在计算第二总和时,可能发生所需的值是第一个单元中的向量的最后行和第二个单元中的向量的第一行。但是,我无法顺序访问不同单元格的元素。
在上面的示例中,修复r = 4的值,结果将是3 x 1的向量:
res = [sum1 sum2 sum3] where
sum1是根据第一个单元格的第一个r = 5行计算的 - >(0.1 + 0.1 + 0.1 + 0.1 + 0.1);
sum2的计算采用下一个r = 5个元素,即第一个单元格中向量的最后一行,第二个单元格中向量的两行以及第三个单元格中向量的前两行 - >(0.1 + 0.2 + 0.2 + 0.04 + 0.04);
sum3是根据下一个r = 5个元素计算的,即第三个单元格中向量的最后三行和第四个单元格中向量的两个第一行以及第三个单元格中向量的前两行 - >(0.04 + 0.04 + 0.04 + 1 + 1);
然后是最后一个单元格的向量的最后一行,其值为1,表示它未被使用且可以降级。
我实际上并不需要所有的中间步骤,只需要所有总和的最终矢量res。但是,我没有得到如何从向量a和b转到res的向量而没有经过这些步骤,在“矩阵构建”的情况下,我遇到了“内存不足”的问题,在这种情况下对于单元格数组,我没有按顺序访问不同单元格中的值。有办法获得解决方案吗?
提前感谢您的任何建议。
约翰
答案 0 :(得分:2)
Notlikethat的答案的变体,它使用乘法而不是加法。对于非常大的输入,这可能会稍快一些,尤其是当r
和平均重复次数(a
中的值)很大时:
a = [6 2 5 3];
b = [0.1 0.2 0.04 1];
r = 5;
nres = floor(sum(a) / r);
result = zeros(1, nres); % preallocate
isrc = 1;
for idest = 1:nres
n_todo = r;
while n_todo > 0
n_possible = min(n_todo, a(isrc));
result(idest) = result(idest) + n_possible * b(isrc);
n_todo = n_todo - n_possible;
a(isrc) = a(isrc) - n_possible;
if a(isrc) <= 0
isrc = isrc + 1;
end
end
end
请注意,它会修改a
,因此如果您仍需要它,请复制一份。结果:
result =
0.5000 0.5800 2.1200
答案 1 :(得分:1)
我知道这是Matlab,每个人都讨厌循环,但如果你的数据很大,那么避免复制它就更重要了。我的C程序员说可以完成整个过程而不需要任何中间副本:
a = [6 2 5 3];
b = [0.1 0.2 0.04 1];
r = 5;
res = zeros(1, floor(sum(a)/r));
srcidx = 1;
srccount = 1;
for destidx = 1:numel(res)
for sumcount = 1:r
if srccount > a(srcidx)
srcidx = srcidx + 1;
srccount = 1;
end
res(destidx) = res(destidx) + b(srcidx);
srccount = srccount + 1;
end
end
此外,有效的慢代码仍然比没有代码的快速代码更好;)
>> res
res =
0.50000 0.58000 2.12000