(以a 开头为 1×m 或 m×1)
解决方案 1
(归功于@Cris Luengo)
abs(a-a.')>z
outer product 类似行为需要 Matlab 2016b 或更高版本。
解决方案 2
使用bsxfun
abs(bsxfun(@minus,a,a.'))>z
解决方案 3
使用repmat
A=repmat(a,fliplr(size(a)));
abs(A-A.')>z
要了解如何处理结果,请参阅 logical arrays 上的数学工作文档。
从技术上讲,您只需要tril 或triu 的结果。
关于速度
循环不在我的考虑范围之内。我在很多场合都看到它很慢。尽管循环在技术上节省了一半的计算量,但它也带来了其他开销。所以我仍然希望矢量化方法更快,我并不认为需要测试循环。即使是内存分配成本高的repmat,也应该更快。
R2018a 中的时序数据见下文。如果您想进行更多测试,您可能希望使用更准确的计时器,例如 this one written in c。为了全面披露,当我测试时,除了 Matlab 之外几乎没有 cpu 需求。我确实尝试过使用和不使用“热身”轮次——特别是因为我确实为我的 cpu 上的某些内核定义了提升行为——但“热身”实际上使每 1000 或 10000 次运行中的数字更糟。也许我的内存跟不上repmat。
基本上,新语法(解决方案 1)的速度非常快。如果您还没有升级,是时候升级了。 bsxfun 是您升级前的最佳选择。 repmat 的内存分配成本太差了。最好避开repmat。
%%%%%%% 1000 x 1000
>> clear all
>> a = randi([-10, 10], [1, 1000]); z=5; N=1000;
>> T=zeros(N,1);tic; for i=1:N; abs(a-a.')>z;T(i)=toc;end; mean(T),
ans =
0.2680
>> clear all
>> a = randi([-10, 10], [1, 1000]); z=5; N=1000;
>> T=zeros(N,1);tic; for i=1:N; abs(bsxfun(@minus,a,a.'))>z;T(i)=toc;end; mean(T),
ans =
1.3556
>> clear all
>> a = randi([-10, 10], [1, 1000]); z=5; N=1000;
>> T=zeros(N,1);tic; for i=1:N; A=repmat(a,fliplr(size(a))); temp=abs(A-A.')>z;T(i)=toc;end; mean(T),
ans =
4.0573
%%%%%%% 100 x 100
>> clear all
>> a = randi([-10, 10], [1, 100]); z=5; N=10000;
>> T=zeros(N,1);tic; for i=1:N; abs(a-a.')>z;T(i)=toc;end; mean(T),
ans =
0.0610
>> clear all
>> a = randi([-10, 10], [1, 100]); z=5; N=10000;
>> T=zeros(N,1);tic; for i=1:N; abs(bsxfun(@minus,a,a.'))>z;T(i)=toc;end; mean(T),
ans =
0.1537
>> clear all
>> a = randi([-10, 10], [1, 100]); z=5; N=10000;
>> T=zeros(N,1);tic; for i=1:N; A=repmat(a,fliplr(size(a))); temp=abs(A-A.')>z;T(i)=toc;end; mean(T),
ans =
0.1815
% Note: assigning the output to a variable or not does not change the result. At least tic toc is not able to detect it.