有上限和下限的cumsum?

Ben*_*n.W 8 matlab vectorization cumsum

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

在我的例子中,输入只包含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
Run Code Online (Sandbox Code Playgroud)

当累积总和达到上限(在第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
Run Code Online (Sandbox Code Playgroud)

你有什么想法?

Lui*_*ndo 5

这是一个有些狡猾的解决方案,但也许值得一提.

您可以使用有符号整数数据类型来执行求和,并利用该数据类型的固有限制.为此,输入需要转换为整数类型并乘以适当的因子,并且需要应用初始偏移量.因子和偏移量被选择作为的函数的lowerupper.之后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
Run Code Online (Sandbox Code Playgroud)

这使

result =
     1     2     3     3     2     1     0     0     0     0
Run Code Online (Sandbox Code Playgroud)