【问题标题】:For loop inside while loopfor 循环内 while 循环
【发布时间】:2019-11-10 22:41:37
【问题描述】:

让我描述一个任务:我有 3 个矩阵 (M1,M2,M3),它们每个都有 lenght(Mi) 行和 2 列。我们得到一个函数g(x,s),其中s 是一个二维参数,xeta 被给出。我想检查第一个矩阵 M1,如果存在诸如 g(x,M1(i,:)>eta 之类的 s,我想结束算法并设置 s_new=M1(i,:)。如果M1 中不存在这样的s,我想去矩阵M2 并在其中搜索。下一个矩阵 M3。如果所有矩阵中都不存在这样的 s_new,我想打破。 我的第一次尝试:

function[s_new]= checking(M1,M2,M3,x)
bool1=0;
eta = 10^-8;
g = @(x,s) x-s(1)-s(2);
while bool1==0
            for i=1:length(M1)
                if g(x,M1(i,:))>eta
                    s_new=M1(i,:);
                    bool1=1;
                end
            end
            for i=1:length(M2)
                 if g(x,M2(i,:))>eta
                    s_new=M2(i,:);
                    bool1=1;
                 end
            end
            for i=1:length(M3)
                 if g(x,M3(i,:))>eta
                    s_new=M3(i,:);
                    bool1=1;
                 end
            end
            bool1=1;
        end

我的第二次尝试涉及一些中断选项,但它也不起作用。问题是:当算法在 M1 中找到 s(例如我们的条件成立)时不会停止,它会转到 M2,如果找到这样的 s,它会更改 s_new。另外为了节省一些时间,如果 M1 中存在这样的 s,我不希望算法通过矩阵 M2。

为什么效果不好的例子:

M1=[0,-1;0,-1], M2=[0,-2;0,-2], M3=[0,0;0,0], x=0 

它应该返回向量[0,-1] 并返回[0,-2]。任何帮助表示赞赏。 编辑:for 循环内的 bool1=1 带有红色下划线,表示 bool1 可能未使用,就好像它在 bool1=0 时没有从开始时的条件识别它一样

【问题讨论】:

    标签: matlab for-loop while-loop


    【解决方案1】:

    我想我找到了问题

    你的意思是打破while循环以防bool1=1;

    您可以在每个部分后添加if bool1, break;end

    %function[s_new]= checking(M1,M2,M3,x)
    M1=[0,-1;0,-1]; 
    M2=[0,-2;0,-2];
    M3=[0,0;0,0];
    x=0;
    
    bool1=0;
    eta = 10^-8;
    g = @(x,s) x-s(1)-s(2);
    while bool1==0
        for i=1:length(M1)
            if g(x,M1(i,:))>eta
                s_new=M1(i,:);
                bool1=1;
            end
        end
        if bool1, break;end
    
        for i=1:length(M2)
             if g(x,M2(i,:))>eta
                s_new=M2(i,:);
                bool1=1;
             end
        end
        if bool1, break;end
    
        for i=1:length(M3)
             if g(x,M3(i,:))>eta
                s_new=M3(i,:);
                bool1=1;
             end
        end
        bool1=1;
    end
    
    display(s_new)
    

    没有while循环会更优雅:

    %function[s_new]= checking(M1,M2,M3,x)
    M1=[0,-1;0,-1]; 
    M2=[0,-2;0,-2];
    M3=[0,0;0,0];
    x=0;
    
    bool1=0;
    eta = 10^-8;
    g = @(x,s) x-s(1)-s(2);
    
    for i=1:length(M1)
        if g(x,M1(i,:))>eta
            s_new=M1(i,:);
            bool1=1;
        end
    end
    
    if ~bool1
        for i=1:length(M2)
             if g(x,M2(i,:))>eta
                s_new=M2(i,:);
                bool1=1;
             end
        end
    end
    
    if ~bool1
        for i=1:length(M3)
             if g(x,M3(i,:))>eta
                s_new=M3(i,:);
                bool1=1;
             end
        end
    end
    
    display(s_new)
    

    【讨论】:

      【解决方案2】:

      添加到@Rotem 的解决方案后,您可以完全摆脱 for 循环来解决您的问题。您可以使用find 函数及其报告满足您条件的第一个索引的能力,而不是遍历所有索引。此外,您也可以完全避免使用变量 bool1。我提出以下代码:

      %function [s_new]= checking(M1,M2,M3,x)
      M1 = [0,-1; 0,-1]; 
      M2 = [0,-2; 0,-2];
      M3 = [0,0; 0,0];
      x = 0;
      eta = 10^-8;
      % Here I have vectorized your function g so that it can work over all the rows of the s matrix. This is the step which actually removes the for-loop. sum(s, 2) always sums over the 2 columns in your matrix.
      g = @(x, s) x - sum(s, 2);
      % Now we assign an empty matrix to s_new. This step gets rid of the bool1 because now we can check whether s_new is still empty or not. It also returns empty matrix if no value of s_new is found in any of your matrices M1, M2 or M3
      s_new = [];
      % Now we find if an s_new exists in M1. We first calculate the g function over the entire M1 matrix. Then we check if your condition is satisfied. Then the find function returns the first row of M1 that satisfies your condition. If it doesnot find any row that satisifies this condition, find will return an empty matrix which we can check to assign the value to s_new
      s_new_index = find(g(x, M1) > eta, 1, 'first');
      if ~isempty(s_new_index) % the isempty function checks for empty matrices. ~ stands for NOT
          s_new = M1(s_new_index, :);
      end
      % Now we check if s_new was assigned earlier. If not then we repeat the same thing with M2 and then M3
      if isempty(s_new)
          s_new_index = find(g(x, M2) > eta, 1, 'first');
          if ~isempty(s_new_index)
              s_new = M2(s_new_index, :);
          end
      end
      if isempty(s_new)
          s_new_index = find(g(x, M3) > eta, 1, 'first');
          if ~isempty(s_new_index)
              s_new = M3(s_new_index, :);
          end
      end
      

      【讨论】:

        猜你喜欢
        • 2018-11-05
        • 1970-01-01
        • 2014-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-29
        • 1970-01-01
        • 2016-04-24
        相关资源
        最近更新 更多