10

我想找到一种向量化的方法来计算向量的累积和,但有上限和下限。

就我而言,输入仅包含 1 和 -1。您可以在答案中使用此假设。当然,也欢迎提供更通用的解决方案。

例如:

x     = [1 1 1 1 -1 -1 -1 -1 -1 -1];
upper = 3;
lower = 0;
s     = cumsum(x)                    %// Ordinary cumsum.
s =
     1     2     3     4     3     2     1     0    -1    -2

y     = cumsumlim(x, upper, lower)   %// Cumsum with limits.
y =
     1     2     3     3     2     1     0     0     0     0
                 ^                       ^
                 |                       |
            upper limit             lower limit

当累积总和达到上限(在第 3 个元素处)时,不再增加。同样,当累积和达到下限(在第 7 个元素处)时,它不会再减少。for 循环版本将是这样的:

function y = cumsumlim(x, upper, lower)

y = zeros(size(x));
y(1) = x(1);

for i = 2 : numel(x)
    y(i) = y(i-1) + x(i);
    y(i) = min(y(i), upper);
    y(i) = max(y(i), lower);
end

end

你有什么想法?

4

2 回答 2

5

这是一个有点骇人听闻的解决方案,但也许值得一提。

您可以使用有符号整数数据类型进行求和,并利用该数据类型的固有限制。为此,需要将输入转换为该整数类型并乘以适当的因子,并且需要应用初始偏移量。选择因子和偏移量作为 和 的lower函数upper。之后cumsum,取消乘法和偏移以获得所需的结果。

在您的示例中,数据类型int8就足够了;所需的因子和偏移量85分别-128为:

x = [1 1 1 1 -1 -1 -1 -1 -1 -1];
result = cumsum([-128 int8(x)*85]); %// integer sum, with factor and initial offset
result = (double(result(2:end))+128)/85; %// undo factor and offset

这使

result =
     1     2     3     3     2     1     0     0     0     0
于 2015-08-06T10:31:01.550 回答
4

我不会为您提供一种神奇的矢量化方法来执行此操作,但我会为您提供一些可能会帮助您继续工作的数据。

您的cumsumlim功能非常快!

tic
for ii = 1:100
    y = cumsumlim(x,3,0);
end
t = toc;
disp(['Length of vector: ' num2str(numel(x))])
disp(['Total time for one execution: ' num2str(t*10), ' ms.'])
Length of vector: 65000
Total time for one execution: 1.7965 ms.

我真的怀疑这是你的瓶颈。您是否尝试过分析代码

于 2015-08-06T08:20:37.440 回答