Loren on the Art of MATLAB

August 29th, 2007

for Versus while

A reader suggested I discuss the difference in use of MATLAB's for and while constructs.

Contents

The Scene

You want to run some code at least once, regardless of any conditions. You might want to run it more often, depending on some conditions.

At Least Once in a while

Here's a couple of solutions using a while construct, while ensuring the main chunk of code is run at least once, even if the stop condition is already met.

  n = 0;
  i = 1;
  while true
       doStuff();
       if (i > n)
           break;
       end
       i = i + 1;
       n = somethingElse();
  end

Here's another way that inverts the logic surrounding the condition and avoids using an explicit break statement. Instead, it has to check to see that currentState is still true.

  n = 0;
  i = 1;
  currentState = true;
  while currentState
       doStuff();
       currentState = (i <= n);
       if currentState,
          i = i + 1;
          n = somethingElse();
       end
  end

I wonder if this version is any better than the first. It is one line longer so currentState can be explicitly set. This might be more readable to some of you, and less so to others.

Taking Care Using for

To make sure the code doStuff runs at least once, we need to take care using a for-loop. The reason for this is that the loop code is guaranteed to not run at all if the loop counter variable is empty. To ensure the code runs once, we need to repeat the code outside the loop. If the code being run is like this example, encapsulated in another function, then it's not so difficult to be sure we've got things right.

If instead of a single function, we have several statements to run, then we have take care to copy all of the code and ensure that we update both sets if we ever have to make some changes.

doStuff will never be run with the following code sample.

  n = 0;
  count = 0;
  for ind = 1:n
      doStuff();
      count = count + 1;
  end

To replicate the run-at-least-once behavior, we need to replicate the code before the loop.

  n = 0;
  count = 0;
  doStuff();
  for ind = 1:n
      doStuff();
      count = count + 1;
  end

Your Style Preferences?

I have to say that having lots of code in the body that might have to be replicated is something I would avoid. So I'd see if I could reasonably stick the bulk of the loop body code in another function. After that, I still have a slight preference for one style over the others, but I'd like to hear your thoughts first.

Which programming style do you prefer here? Using for, while with an explicit condition, while with a break, or do you have an even better code pattern? Post your thoughts here.


Get the MATLAB code

Published with MATLAB® 7.5

27 Responses to “for Versus while”

  1. Jeremy replied on :

    Loren says:
    doStuff will never be run with the following code sample.

    n = 10;
    count = 0;
    for ind = 1:n
    doStuff();
    count = count + 1;
    end

    Why not? I tried it in my Matlab session and doStuff is called 10 times as I would expect.

  2. Loren replied on :

    Jeremy-

    I will have to edit the code again. Some of the code that’s wrong! Thanks for letting me know. And it’s now fixed.

    –Loren

  3. Markus replied on :

    Hi Loren,

    First I avoid writing code twice if ever possible! I have just “demultiplexed” code of a student of mine where about 30 lines were repeated 4 times with only little differences. Horrible!

    Second I avoid using “i” and “j” as loop counters, as they might be used as the imaginary unit in some other place.

    And your second example with currentState looks a little complicated to me. I more like to use a break statement.

    Regards
    Markus

  4. Jos replied on :

    Hi Loren,

    What about the following for-construct, which mimicks your “at least once in a while”, but is shorter

      for i=1:Inf
        disp(i) ; % Do Stuff
        n = 10 * rand(1) ; % your somethingElse();
        if i > n
          break ;
        end ;
      end
    

    Jos

  5. Daniel Armyr replied on :

    Although I sometimes use the duplicate-code-with-for-loop I hide my face in shame each time.

    The break version would be really great, the problem is when you start nesting loops the break only exits the innermost loop. With explicit conditions you have more control of what happens when your exit condition is met.

  6. OkinawaDolphin replied on :

    I think the second example with a while loop is best. It is very clear that the loop is run at least once. It is also clear that the number of runs is not known in advance.

    Contrasting this, the first example can be mistaken as an endless loop. A comment that explains what the programmer actually wanted to achieve by this loop would require several lines in a real world application.

    I dislike the for loop example for the same reason: Usually the number of for loop runs is known and determined in advance. Again a comment would be necessary to explain what the programmer really meant.

    C++ has a do{}while statement, Pascal has a repeat until statement. It would be nice to have something like this in Matlab, too.

  7. Dan K replied on :

    Loren,
    I agree with Okinawa, but I would go even one step further still. My preference is to use a flag variable, which allows me to test for any number of stopping conditions, and keep track of why I stopped. I took this approach from the optimization toolbox, and have found it invaluable for tracking possible occurrences when handling large sets of data.

    Dan

  8. Loren replied on :

    Folks,

    Thanks for your thoughtful comments.

    I prefer the explicit conditions as well. It makes it possible to manage more than 1, as people stated, and it is possible to manage the details outside the loop later, if desired as well. That helps with the nested loop situation, vs. using break.

    –Loren

  9. Toby Driscoll replied on :

    How about for i=1:max(1,n) to guarantee at least one loop pass?

    Loren, can you say anything about execution speed of for versus while? Is it possible for one version to be accelerated when the other is not?

  10. Loren replied on :

    Toby-

    Acceleration typically depends on the contents of the loop statements, and not on whether you use for or while. If variables don’t change shape or type from iteration to iteration, the code has a higher chance of being accelerated.

    –loren

  11. Dan K replied on :

    Loren,
    The question about acceleration got me thinking about a item I’ve found in the past which I really don’t understand. The profiler often reports the end statement of a loop as using a substantial amount of time (well, substantial when executed several tens of thousands of times). I thought that the end statement was really just a marker with virtually no execution time, but that doesn’t seem to be the case. Where is the time used in implementation of a for vs. a while loop. How does condition testing (while) compare against index creation (for)?

    Thanks,
    Dan

  12. Tim Davis replied on :

    Regarding the use of “i”. I think using i and j as complex scalars is a bad idea. You can never trust that they haven’t been overwritten with something else (like row and column indices as they ought to be used, in my mind). For the complex sqrt(-1), I always 1i, which is always the imaginary unit no matter what your variables do.

  13. lehalle replied on :

    According to me, the main difference between while and for loops in matlab is this one:

    u = [];
    for n=1:10
    if n==3
    n=n+1;
    end
    u = [u, n];
    end
    u

    has not the same behavior than

    u = [];
    n=1;
    while n
    I remember how I had to modify a lot of lines of MATLAB codes when the behavior of for changed (with R14?) around 6 years ago…

  14. lehalle replied on :

    oops, my two pieces of code were:

    u = [];
    for n=1:10
    if n==3
    n=n+1;
    end
    u = [u, n];
    end
    u

    and

    u = [];
    n=1;
    while n

  15. lehalle replied on :

    ok, let’s try once more the while part:

    u = [];
    n=1;
    while n<=10
    if n==3
    n=n+1;
    end
    u = [u, n];
    n=n+1;
    end
    u

  16. Steve Johnson replied on :

    There’s a pattern I use a lot with M to address Loren’s original problem. It looks like:

    work = true;
    while( work )
    work = false;

    if
    work = true;
    % sometimes I put CONTINUE here for emphasis
    end
    end

    With a bit of care, this pattern can be nested, too…

    This is especially good for tasks that have a “massage something until it stops changing” flavor.

  17. Loren replied on :

    Dan,

    With respect to the end statement appearing to take all the time, I will try to give you a high-level answer.

    In M code, the end statement is not 100% equivalent to an end statement in C. It does more than just close the loop. There’s a loop counter that is incremented at this point to check to see if the loop is done. Next compute the loop control variable for the next iteration. Check for Ctrl-C, etc. These all take some time. In addition, assuming the JIT is operating during the for loop, when appropriate, the variables used by the JIT need to be returned back fully into the main MATLAB context.

    while loops differ in when the loop expression is evaluated (at the top) vs. the for loop. So in that case, some of the time might get assigned to the while statement and not the end.

    I hope this gives you enough of a flavor of what’s happening.

    –Loren

  18. Dan K replied on :

    Loren,
    Thank you for the response. I understand now the usage of time in this stage of the program (although I wasn’t aware that ML checked for a Cntrl-C at the ends of loops - Does this mean that if I have a loop buried in my code, it’s cycle time is longest delay that I will ever have to wait for an abort to kick in? If so, then I may consider adding single pass for loops in some spots as an escape hatch.)

    One other follow on question: I really started with MatLab in version 7, so my understanding of the JIT is somewhat limited. Is there a bible of JIT somewhere that explains what is acceleratable (excuse the imaginative word definition) and what is not?

    Thanks,
    Dan

  19. Loren replied on :

    Dan-

    There are a few of my blog posts that talk about the JIT a little and you might find some discussion on the MATLAB documentation. But there’s intentionally not a lot of information. Why? Because it is a rapidly moving target and we don’t want to encourage people to program to the details of any particular version. Instead, we hope people will write readable, maintainable code that runs fast enough without having to perform contortions and that code will benefit over time with our ongoing investment in performance. If something in particular is very slow, it is worth sending the code to tech support so it can get on the development radar for performance improvements.

    The thing about Cntrl-C is that if you don’t time the action, it can miss the window. So I don’t think you will necessarily get the behavior you want by rewriting your loop. Perhaps it’s worth you trying it though.

    –Loren

  20. Felipe G Nievinski replied on :

    I really like Toby Driscoll’s construct, e.g.:

    n = 2; for i=1:max(1,n), disp(’hw!’); end
    hw!
    hw!

    n = 0; for i=1:max(1,n), disp(’hw!’); end
    hw!

    I find it even better than the while true construct I used to prefer.

  21. chtorregrosa replied on :

    advertise to C programmers to take care with this statement

    for i = 1:3
    i = 1
    end

    it will loop three times!!! the similar code in C never will stop.

    for(i=1;i

  22. Diane Kelly replied on :

    The following code runs three times and ends with i equal to 8
    for i=1:3
    i=i+5
    end
    i

    I’m curious how the loop counter is actually manipulated and at what point it is checked to see if the loop end condition is satisfied. Is the i+5 actually put into a different storage location than the loop counter?

  23. Loren replied on :

    Diane-

    The loop counter gets reset each time through the loop, despite what might happen within the loop.

    –Loren

  24. German replied on :

    I am doing some nested while loops, but in the inner while loop I have a for loop inside of it, then I have a condition that needs to break the while loop but since break applies to the for loop also I wonder how I do it?, do you need a sample of it?

  25. Loren replied on :

    German-

    What you may need to do is to set a variable in the inner loop (switch between true and false if you break). In the outer loop, check to see if the inner loop broke or not and act accordingly.

    –Loren

  26. Natarajan replied on :

    Hi Loren,

    I wrote a program for processing images of size 4008 x4008.

    When i executed the code,the code runs for almost 2 days.Also if i change the input data as 8-bit,i do get a result but if i give the original 16-bit data as input..an error is thrown stated as out of memory exception.(Help memory)..

    Actually i need several instances of the image and there was an inherent need to use several for loops.Could this cause a overhead.( it suggested me to consider preallocating for speed but there is a memory limitation along with the speed).

    so i am wondering if while is better than for loop.?

    I would appreciate if you could give me a light on this part.It would be great if Matlab could provide few materials about code optimization in Matlab.

  27. Loren replied on :

    Natarajan-

    You have not provided enough information for me to have any insight. I recommend you contact support (link on the right side) with more details and they will help you out. Off-hand, for and while loops are neither worse nor better than each other - but used for different purposes typically.

    The profiler, M-Lint, and the last 3 sections of the MATLAB documentation under Programming Fundamentals:

    http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/bqjgwp9.html

    have a lot of advice for code optimization.

    –Loren

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Jun: I totally can not believe it, Loren. You are really helpful. Thank you so much, MATLAB master!
  • Loren: Wow folks- Always lots of interest when there’s a quickie to try out! I will only make 2 general...
  • Loren: Jun- ismember is your friend here: >> [aa,ind] = ismember(Array2,Arra y1) aa = 1 1 1 1 1 1 1 ind = 1 2 1 4 4 3...
  • Dan: I like the first way better than the second way. Combining the arrays into one and running any is nice, although...
  • James Myatt: How about I = (a == 0 | b == 0); a(I) = []; b(I) = [];
  • Tunc: Hello Loren, love your blog because of such inspiring and challenging comments to such ’small’...
  • Pekka Kumpulainen: Here is my tradeoff. I usually want to keep the original variables as they are most probably...
  • Iain: Followup: Of course, to allow NaNs (counting them as non-zero): mask = (a~=0) & (b~=0); The mask says “a...
  • Matt Fig: I would usually go with something like this: y = a&b; x = a(y); y = b(y); But I was surprised to find...
  • kk: c=all([a;b]) a(c) a(b)

These postings are the author's and don't necessarily represent the opinions of The MathWorks.