2017-11-25 115 views
0

正如标题所说,我正在寻找一个这个动态版本,但我无法弄清楚如何做到这一点。在这种情况下,r = 30,并且情况之间的差异是5(我< = 5,我< = 10,1 < = 15等)有人可以帮助我吗?我怎样才能以更动态的方式来写这个?

for i = 1:r 
    if  i <= 5 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(1) 
    elseif i <= 10 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(6) 
    elseif i <= 15 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(11) 
    elseif i <= 20 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(16); 
    elseif i <= 25 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(21); 
    elseif i <= 30 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(26); 
    end 
    if a_m_o(i)<0 
    a_m_o(i) = a_m_o(i) + 400; 
    end 
end 

回答

0
r_help=repmat([1:5:length(r)],[5,1]); %create a helper vector which got the indices in it which you need. 
r_help=r_help(:); 

for i = 1:r 
    a_m_o(length(a_m_o)+1) = m_o(i) - m_o(r_help(i)); 
    if a_m_o(i)<0 
     a_m_o(i) = a_m_o(i) + 400; 
    end 
end 
2

基本上,你组自然数(不含零)5(或n)元件的连接图中的每个元件组中的其第一元件的基团。这样的操作可以典型地使用模来完成:

function k = map (i) 
    n = 5; 
    m = mod(i, n); 
    if m == 0 
     m = 5; 
    end 
    k = i - m + 1; 
end 

这将映射到1, 2, 3, 4 and 51; 6, 7, 8, 9 and 106; ...

3

其他答案指导你避免代码重复。但你需要做的另一件事是vectorize your code。向量化是一种避免循环的方式,在MATLAB中相对较慢(即使现在比我开始使用MATLAB时快得多)。

I = floor(((1:r)-1)/5)*5+1; 

这将创建一个数组[1,1,1,1,1,6,6,6,6,6,11,11,...]

首先我们将创建一个数组的索引m_o您在循环做的方式启动。您也可以按照其他答案中的建议使用repeatmod

索引m_o使用Im_o(I))与编写[m_o(1),m_o(1),m_o(1),m_o(1),m_o(1),m_o(6),m_o(6),m_o(6),...]相同。也就是说,我们将索引相同元素5次,在输出数组中创建该元素的5个副本。所以现在你可以这样写:

a_m_o = a_m - a_m(I); 

您的阴性结果的测试,也可向量化:

J = a_m_o < 0; 
a_m_o(J) = a_m_o(J) + 400; 

除此之外量化代码是更快,它往往也更容易了很多阅读!

另请注意,您的代码a_m_o(length(a_m_o)+1) = ...效率非常低:数组a_m_o在每次循环迭代时调整大小。较新的MATLABs实际上识别这个用例和它周围的优化,但它仍然要快得多pre-allocate the array

a_m_o = zeros(size(m_o)); 
for i = 1:r 
    a_m_o(i) = a_m(i) - a_m(1); 
end 

对于r=30你可能不会注意到其中的差别,但对于更大的阵列节省的费用是巨大的。

相关问题