应用于数组的Linspace [重复]

问题描述 投票:1回答:3

这个问题在这里已有答案:

给定像a = [ -1; 0; 1];这样的数组。对于每个a(i),我需要使用linspace(min(a(i),0),max(a(i),0),3);计算线性间隔向量,其中每个linspace-vector应存​​储到矩阵中:

A = [-1 -0.5 0;
      0   0  0;
      0  0.5 1];

使用for循环,我可以这样做:

for i=1:3
    A(i) = linspace(min(a(i),0),max(a(i),0),3);
 end

如何在不使用循环的情况下实现此目的?

matlab vectorization
3个回答
6
投票

我能想到的最快的方法是计算步长,使用隐式二进制扩展从中构造向量。

 a = [ -1; 0; 1];
 n = 3;
 stepsizes = (max(a,0)-min(a,0))/(n-1);
 A = min(a,0) + (0:(n-1)).*stepsizes;

Timeit:

几个timeit结果使用(使用timeit(@SO)并删除块中的注释以进行定时):

function SO()
n = 1e3;
m = 1e5;
a = randi(9,m,1)-4;

% %Wolfie
% aminmax = [min(a, 0), max(a,0)]';
% A = interp1( [0,1], aminmax, linspace(0,1,n) )';

% %Nicky
% stepsizes = (max(a,0)-min(a,0))/(n-1); 
% A = min(a,0) + (0:(n-1)).*stepsizes;

% %Loop
% A = zeros(m,n);
% for i=1:m
%     A(i,:) = linspace(min(a(i),0),max(a(i),0),n);
% end

%Arrayfun:
A = cell2mat(arrayfun(@(x) linspace(min(x,0),max(x,0),n),a,'UniformOutput',false));

那么时间是:

  • 沃尔夫:2.2243 s
  • 我的:0.3643秒
  • 标准循环:1.0953秒
  • arrayfun:2.6298 s

4
投票

a = [ -1; 0; 1]为例。创建最小/最大数组:

aminmax = [min(a, 0), max(a,0)].';

现在使用interp1

N = 3; % Number of interpolation points.
b = interp1( [0,1], aminmax, linspace(0,1,N) ).';

>> b = 
      -1.0000   -0.5000         0
       0         0              0
       0         0.5000         1.0000

0
投票

一种可能的解决方案是使用arrayfun将函数应用于数组的每个元素。您还希望将结果转换为矩阵,因为输出位于单元数组中。由于arrayfun的输出是非标量的,因此必须关闭均匀输出。

cell2mat(arrayfun(@(x) linspace(min(x,0),max(x,0),3),a,'UniformOutput',false))

编辑:我在100000长阵列上使用tic-toc方法进行了一些测试。我发现,arrayfun的解决方案需要大约。比你建议用于循环的时间长1.5倍。

最快的方法是使用矩阵向量运算来计算所需的内容。例如,如果您只需要计算3个元素的linspace,您可以使用以下内容:

[min(a(:),0), (max(a(:),0)+min(a(:),0))/2 ,max(a(:),0)];

您可以将此方法概括为linspace函数中的任意数量的元素(不一定只是3)。请注意,随着代码量的增加,可读性将受到影响:

 j=4; % number of elements in each linspace
 b=zeros(size(a,1),j); % create a solution matrix of size Nxj
 b(:,1)=min(a(:),0); %first row
 b(:,end)=max(a(:),0); % last row
 temp=b(:,1)+b(:,end); % sum of the first and the last row
 for i=2:j-1
     b(:,i)=temp*(i-1)/(j-1); % fill in intermediate rows
 end

注意,在这个方法中,我循环遍历每个linspace中的元素数,但不是通过数组a。对于小j(在你的例子中就像j = 3),与循环遍历数组a的方法相比,这将更快地工作(如果考虑像a=rand(100000,1)这样的大型数组)。

© www.soinside.com 2019 - 2024. All rights reserved.