【问题标题】:MATLAB: For loop structure [duplicate]MATLAB:For循环结构[重复]
【发布时间】:2016-06-23 03:56:04
【问题描述】:

这是一个基本程序,但由于我是 MATLAB 新手,所以我无法找出解决方案。

我有一个列向量“时间”,我想在前 147 个单元格中打印值“1”,然后在 148 到 2*147 个单元格中打印“2”,依此类推。为此,我编写了以下脚本:

 Trial>> c=1;
 Trial>> k=0;
 Trial>> for i = c:146+c
            Time(i,1)=1+k;
            c=i;
            k=k+1;
            end

我知道我需要在 "Time(i,1)=1+k;" 上迭代循环在它执行下一条语句之前。我尝试使用 break 但这不应该工作。任何人都可以建议我获得所需结果的解决方案吗?(在 C 中非常简单,只需使用花括号。)

【问题讨论】:

  • 我不太明白你想要什么。输出预计为121212...111..11222..222? Matlab的for循环是线性迭代,你的for循环结构有点怪。

标签: matlab for-loop vector


【解决方案1】:

我确定您不想在每次迭代中都运行 c=i;

我的代码应该适合你:

x = 10; % Replace 10 by the max number you need in your array.
k = 1;
for i = 1 : x * 147
    Time(i, 1) = k;
    if rem(i, 147) == 0
        k = k + 1;
    end
end

【讨论】:

  • @dora 请同时考虑其他答案。虽然这是一个正确的解决方案,但我认为它是最差的(就 Matlab 的有效使用而言)
【解决方案2】:

这是一段代码的主要例子,应该是vectorized可以帮助你理解vectorization。你的代码可以这样写:

n = 147;
reps = 10; %% Replace this by the maximum number you want your matrix to have

Time = reshape(bsxfun(@plus, zeros(n,1), 0:reps), 1, []);

说明:

A 为列向量(1 列,n 行),B 为行向量(1 行,m 列。

bsxfun(@plus, A, B) 在这里要做的是将A 中的所有元素与B 中的所有元素相加,如下所示:

A(1)+B(1)  A(1)+B(2)  A(1)+B(3) ... A(1)+B(m)
A(2)+B(1)  A(2)+B(2)  ............. A(2)+B(m)
............................................
A(n)+B(1)  A(n)+B(2) .............. A(n)+B(m)

现在,对于我们拥有的两个向量:zeros(n,1)0:reps,这将给我们;

0+0        0+1        0+2           0+reps
0+0        0+1        0+2           0+reps
% n rows of this

所以,我们现在需要做的是将每一列放在彼此的下方,这样一来,您将首先获得带有 0 的列,然后是带有 1 的行,...最后是带有 reps 的行(147 in你的情况)。

这可以通过reshaping矩阵来实现:

reshape(bsxfun(@plus, zeros(n,1), 0:reps), [], 1);
^       ^                                  ^   ^
|       |                                  |   Number of rows in the new matrix. When [] is used, the appropriate value will be chosen by Matlab
|       |                                  Number of rows in the new matrix
|       matrix to reshape
reshape command   

另一种方法是使用kron

kron(ones(reps+1, 1) * 0:(n-1)

作为记录,对您的代码进行审查:

您应该始终为循环内创建的矩阵预先分配内存。在这种情况下,您知道它将成为维度矩阵((reps+1)*n-by-1)。这意味着你应该做Time = zeros((reps+1)*n, 1);。这将大大加快您的代码速度。

您不应该在 Matlab 中使用 ij 作为变量名,因为它们表示虚数单位 (sqrt(-1))。例如,您可以这样做:for ii = 1:(n*147)

当循环应该从 c 转到 c + 146 时,您不希望 c=i 在循环内。这没有多大意义。

【讨论】:

  • 你真的认为bsxfunreshape 是最好的解决方案吗? a=floor((0:(n*reps-1))/n) 怎么样(更快)
  • bsxfunreshape始终是最佳解决方案。 bsxfunreshapepermute 是第二好的……当然,除非有更好更快的替代方案。 =P 我建议您将其发布为答案,您将获得我的支持!我没有想到它,是的,它可能比我的更好。在我看来,虽然阅读起来有点困难,但并不多。
  • 我可以阅读,我总是与bsxfun 混淆:)
  • 好吧,我总是要考虑行和列,rdivideldivide。结合reshape 之类的东西,我在第一次尝试时从来没有正确过,我敢打赌你的第一次尝试也不正确;)
  • 不,我的第一次尝试远非正确。然而,我的第二次尝试也是……错了。我想我可能在第十次尝试时是正确的,在第 20 次尝试时又是正确的。一旦我将permute 包含在其中,我就犯了更多错误……但话又说回来,我创造了无数的无限循环、索引错误、这个世界之外的瓶颈等等……我问了this 三年的问题以前……现在都快尴尬了!那些日子我绝对不明白bsxfun,,,
【解决方案3】:

你可以使用repmat

x = 10; % Sequence length (or what ever it can be called)
M = repmat(1:x,147,1); % Replicate array 1:x for 147 columns
M = M(:); % Reshape the matrix so that is becomes a column vector.

我可以假设这是一个练习 for 循环的任务,但这会奏效。

【讨论】:

  • +1,我没有测试过,但我认为这胜过@Bernards 的方法……它绝对胜过其他方法……
【解决方案4】:

另一种解决方案可能是这样做

n = 147;
reps = 10;
a = ceil( (1:(n*reps)) / n);

你首先构造一个你想要的长度的数组。然后你分裂,向上循环。然后 1 到 147 将变为 1。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 2015-07-13
    • 2019-03-10
    • 2017-07-27
    • 1970-01-01
    相关资源
    最近更新 更多