1

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

z=??
for i=1:inf
    z(i,1)=i;
    if(condition)%%condition is met then break out of the loop
        break;
    end;
end;
4

5 回答 5

2

请首先注意这是不好的做法,您应该尽可能预先分配。

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

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

您还可以连接先前迭代的结果,这往往会更慢,因为您在等号运算符的两侧都有赋值变量

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

萨达尔评论说,直接索引越界(正如其他答案所暗示的那样)被 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
于 2018-08-15T08:16:14.850 回答
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 或您选择的任何其他字母作为您的首选循环索引变量名称,即使您不处理复杂的值职能 ;)

于 2018-08-15T07:56:00.400 回答
0

你可以声明一个空矩阵

z = []

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

请记住,这比使用 zeros(dim,dim) 函数预先初始化向量要慢得多。因此,如果有任何方法可以计算出 i 的最大值,您应该将其初始化为z = zeros(i,1)

干杯,西蒙

于 2018-08-15T06:13:49.300 回答
0

您可以将 z 初始化为一个空数组,它会在循环过程中自动扩展......类似于:

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

然而,这看起来很讨厌(并引发警告:警告:FOR 循环索引太大。截断为 9223372036854775807),我会在这里做一段时间(真)或条件本身并手动递增。

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

和/或如果您的示例最终确实是您所需要的,请将数组的重新创建替换为:

while !condition
 i=i+1;
end
z = 1:i;
于 2018-08-15T06:18:50.347 回答
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

希望这可以帮助!

于 2018-08-15T08:55:59.087 回答