在Matlab中声明一个未知大小的向量

时间:2018-08-15 05:58:37

标签: matlab variable-declaration pre-allocation

假设我们在MATLAB中运行无限循环,并且要将迭代值存储在向量中。我们如何在不知道向量大小的情况下声明向量?

setting -> Apps

5 个答案:

答案 0 :(得分:2)

请首先注意,这是一种不好的做法,您应该在可能的情况下进行预分配。

话虽如此,使用end关键字是将数组扩展为单个元素的最佳选择:

z = [];
for ii = 1:x
    z(end+1, 1) = ii; % Index to the (end+1)th position, extending the array
end

您还可以连接先前迭代的结果,由于您在equals运算符的两边都具有赋值变量,因此这往往会比较慢

z = [];
for ii = 1:x
    z = [z; ii];
end

Sadar commented直接超出范围(如其他答案所暗示),索引已被MathWorks贬值,我不确定这方面的消息来源。


如果您的condition计算与输出计算是分开的,则可以先获得所需的大小

k = 0;
while ~condition
    condition = true; % evaluate the condition here
    k = k + 1;
end

z = zeros( k, 1 ); % now we can pre-allocate
for ii = 1:k
    z(ii) = ii; % assign values
end

答案 1 :(得分:1)

根据您的用例,您可能不知道实际的迭代次数,因此也不知道矢量元素,但是您可能知道最大可能的迭代次数。如前所述,在每次循环迭代中调整向量的大小可能是一个真正的性能瓶颈,您可能会考虑如下情况:

maxNumIterations = 12345;
myVector = zeros(maxNumIterations, 1);

for n = 1:maxNumIterations
    myVector(n) = someFunctionReturningTheDesiredValue(n);

    if(condition)
        vecLength = n;
        break;
    end
end

% Resize the vector to the length that has actually been filled
myVector = myVector(1:vecLength);

顺便说一句,我会建议您不要习惯在Matlab程序中将i用作索引,因为这会掩盖虚构的i。我这样做会在循环内遇到复杂计算中的一些讨厌的错误,因此我建议即使您未处理复杂的值,也建议仅将n或您选择的任何其他字母用作循环索引变量名称功能;)

答案 2 :(得分:0)

您可以使用声明一个空矩阵

z = []

这将创建一个0x0矩阵,当您向其中写入数据时会调整大小。 在您的情况下,它将增长为向量ix1。

请记住,这比用zeros(dim,dim)函数预先初始化向量要慢得多。 因此,如果有办法找出i的最大值,则应使用z = zeros(i,1)

对其进行初始化。

欢呼声, 西蒙

答案 3 :(得分:0)

您可以将z初始化为一个空数组,它会在循环过程中自动展开...如下所示:

z = [];
for i = 1:Inf
 z(i) = i;
 if (condition)
    break;
 end
end

但是这看起来很讨厌(并发出警告:警告:FOR循环索引太大。截断为922337203685477575807),我会在这里做一会儿(true)或条件本身,然后手动递增。

z = [];
i = 0;
while !condition
 i=i+1;
 z[i]=i;
end

和/或如果您的示例确实是您最后所需的内容,请使用类似以下内容的方法替换数组的重新创建:

while !condition
 i=i+1;
end
z = 1:i;

答案 4 :(得分:0)

正如在该线程中多次提到的那样,数组的大小调整需要大量处理,并且可能要花费大量时间。

如果处理时间不是问题:

然后像@Wolfie这样的东西就足够了。在每次迭代中,数组长度都会增加,即:

z = [];
for ii = 1:x
    %z = [z; ii];
    z(end+1) = ii % Best way
end

如果处理时间有问题:

如果处理时间是一个很大的因素,并且您希望它尽可能平稳地运行,则需要进行预分配。如果您对将要运行的最大迭代次数有一个大概的了解,则可以使用@PluginPenguin的建议。但是仍然可能会达到该预设限制,这将破坏(或严重降低)程序的速度。

我的建议:

如果循环一直无限运行直到停止,则可以偶尔调整大小。从本质上讲,可以扩展大小,但偶尔需要做一次。例如,每100个循环:

z = zeros(100,1);
for i=1:inf
    z(i,1)=i;

    fprintf("%d,\t%d\n",i,length(z)); % See it working

    if i+1 >= length(z)  %The array as run out of space
        %z = [z; zeros(100,1)];   % Extend this array (note the semi-colon)
        z((length(z)+100),1) = 0; % Seems twice as fast as the commented method
    end

    if(condition)%%condition is met then break out of the loop
        break;
    end;
end

这意味着循环可以永远运行,数组会随之增加,但偶尔会增加一次。这意味着处理时间将最短

编辑:

正如@Cris所提到的,MATLAB已经完成了我内部提出的建议。这使我的两条评论完全错误。因此,最好的方法就是遵循@Wolfie和@Cris所说的话:

z(end+1) = i

希望这会有所帮助!