有上限和下限的cumsum?
cumsum with upper & lower limits?
我想找到一个向量化的方法来计算一个向量的累加和,但是有上限和下限。
在我的例子中,输入仅包含 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
你有什么想法吗?
我不会为您提供神奇的矢量化方法来执行此操作,但我会为您提供一些可能会帮助您继续工作的数据。
您的 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.
我真的怀疑这是你的瓶颈。你试过了吗profiling the code?
这是一个有点 hackish 的解决方案,但也许值得一提。
您可以使用有符号整数数据类型 求和,并利用该数据类型的固有限制。为此,需要将输入转换为该整数类型并乘以适当的 factor,并且需要应用初始 offset .选择因子和偏移量作为 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
我想找到一个向量化的方法来计算一个向量的累加和,但是有上限和下限。
在我的例子中,输入仅包含 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
你有什么想法吗?
我不会为您提供神奇的矢量化方法来执行此操作,但我会为您提供一些可能会帮助您继续工作的数据。
您的 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.
我真的怀疑这是你的瓶颈。你试过了吗profiling the code?
这是一个有点 hackish 的解决方案,但也许值得一提。
您可以使用有符号整数数据类型 求和,并利用该数据类型的固有限制。为此,需要将输入转换为该整数类型并乘以适当的 factor,并且需要应用初始 offset .选择因子和偏移量作为 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