【发布时间】:2014-05-25 16:08:55
【问题描述】:
我有一个实数列向量 (V1),例如:
123.2100
125.1290
...
954.2190
如果我在这个向量中的每一行添加一个数字 1,我将得到 (V2):
124.2100
126.1290
...
955.2190
我需要找出有多少来自 V2 的元素在从 V1 创建的某个错误窗口中。例如 error-window = 0.1 (但在我的情况下,V1 中的每个元素都有自己的错误窗口):
123.1100 123.3100
125.0290 125.2290
...
954.1190 954.3190
我可以创建一些这样的代码:
% x - my vector
% ppm - a variable responsible for error-window
window = [(1-(ppm/1000000))*x, (1+(ppm/1000000))*x]; % - error-window
mdiff = 1:0.001:20; % the numbers I will iteratively add to x
% (like the number 1 in the example)
cdiff = zeros(length(mdiff),1); % a vector that will contain counts of elements
% corresponding to different mdiff temp = 0;
for i = 1:length(mdiff)
for j = 1:size(window,1)
xx = x + mdiff(i);
indxx = find( xx => window(j,1) & xx <= window(j,2) );
if any(indxx)
temp = temp + length(indxx); %edited
end
end
cdiff(i) = temp;
temp = 0;
end
因此,最后 cdiff 将包含与 mdiff 对应的所有计数。唯一的事情,我想让代码更快。或者有没有办法避免使用第二个循环(带j)?我的意思是直接使用多维条件。
编辑
我决定像这样简化代码(感谢我在这里得到的反馈):
% x - my vector
% ppm - a variable responsible for error-window
window = [(1-(ppm/1000000))*x, (1+(ppm/1000000))*x]; % - error-window
mdiff = 1:0.001:20; % the numbers I will iteratively add to x
% (like the number 1 in the example)
cdiff = zeros(length(mdiff),1); % a vector that will contain counts of elements
% corresponding to different mdiff temp = 0;
for i = 1:length(mdiff)
xx = x + mdiff(i);
cdiff(i) = sum(sum(bsxfun(@and,bsxfun(@ge,xx,window(:,1)'),bsxfun(@le,xx,window(:,2)'))));
end
在这种情况下,代码运行得更快并且看起来正确
【问题讨论】:
-
我相信您可以使用二进制搜索之类的方法来避免进行所有 n² 次迭代。先对V1进行排序,然后对每一个V2,与V1的中项进行比较,看是高于还是低于它。如果它较低,则无需检查 V1 的上半部分。继续下去,直到找到匹配项,或者直到你用完候选人
-
一些小cmets:不用
find,直接用if any(xx <= ... & xx >= ...)即可。接下来,将xx = ...移动到第二个for 循环之前,因为它不会随着j而改变。您更大的问题是您的算法需要O(n * m^2)时间,其中n = length(mdiff)和m = length(x)。 -
@BasSwinckels 感谢您的评论
-
@Kirill 确保 EDIT 代码与原始代码相比产生匹配值。
-
@Divakar,是的,它产生了。在我的原始版本中,我唯一需要改变的是不要使用
temp = temp + 1,而是使用temp = temp + length(indxx)。感谢您的帮助!
标签: arrays matlab conditional-statements