CSC 161  Grinnell College  Spring, 2010 
Imperative Problem Solving and Data Structures  
This laboratory exercise introduces the concept of loop invariants and provides some practice in using loop invariants in developing programs.
Consider the following problem from the reading.
Problem: Read a (nonzero) number r from the keyboard and compute (and print) r^{0}, r^{1}, r^{2}, r^{3}, ..., r^{10}.
The reading specifies three solutions to this problem, and these solutions are given in program loopinvariants1.c
Review the following code segment from the reading.
printf ("First Solution\n"); prod = 1; i = 0; while (i <= 10) { printf ("\t%6.2lf", prod); prod *= r; i++; } printf("\n");
Next, review Code Segment 2:
printf ("Second Solution\n"); printf ("\t%6.2lf", 1.0); prod = 1; i = 0; do { i++; prod *= r; printf ("\t%6.2lf", prod); } while (i < 10); printf("\n");
Last in this group of solutions is Code Segment 3:
printf ("Third Solution\n"); printf ("\t%6.2lf", 1.0); prod = r; printf ("\t%6.2lf", prod); i = 0; while (i < 9) { i++; prod *= r; printf ("\t%6.2lf", prod); } printf("\n");
Consider the following problem, which is a variation of the previous problem.
Problem 2: Read a number r from the keyboard and compute (and print) r^{10}. In your computation, use successive multiplications in your computation rather than relying upon any builtin functions or library functions.
Note that Problem 2 asks you to compute the same final value as Problem 1, but here the smaller powers of r are not to be printed.
Using the previous program in this lab as motivation, we can approach this problem in several ways, with variables i and prod keeping track of where we are within a computation. Finally, when our computation is complete, we can print the result. In each case, details of the work will depend upon the particular loop invariant chosen.
Following Part 1's Code Segment 1, we might chose our loop invariant to be:
Such an invariant might suggest code of the general form:
printf("First Approach\n"); prod = ??; i = ???; while (i <= ????) { prod *= r; i++; } printf("%6.2lf\n", prod);
Fill in the question marks in a way consistent with the above loop invariant and in a way that generates the appropriate final value for prod. Place your code in a program shell to demonstrate that your code works correctly.
Explain why your initialization and loopcontinue condition are consistent with this loop invariant.
Use the loop invariant and your loopcontinue condition to explain why your code generates the correct result.
A second solution to Problem 2 uses the same loop invariant in the context of a dowhile loop, paralleling Code Segment 2 from Part 1.
printf("Second Approach\n"); prod = ??; i = ???; do { i++; prod *= r; } while (i < ????); printf("%6.2lf\n", prod);
Fill in these question marks, again based upon this loop invariant, and test the resulting code in a program.
Explain the correctness of your code as before, basing your answer on your loop invariant and loopcontinue condition.
A third solution might use the loop invariant for the earlier Code Segment 3:
Such an perspective might yield code of the following form:
printf("Third Approach\n"); prod = ??; i = ???; while (i < ????) { i++; prod *= r; } printf(prod"%6.2lf\n", );
Again, fill in appropriate values for these questions marks, based on this new loop invariant, and test your code.
Paralleling your previous work in this part, explain why the resulting code is correct.
Consider the problem of reading successive numbers from the keyboard, until a nonpositive value is read, and finding the average of the positive values. For example, if the numbers 1, 2, 3, 4, 5, 1 are entered, then the average of 1, 2, 3, 4, 5 is computed, and the resulting value (3.0) is printed.
Program loopinvariants2.c shows five code segments that attempt to solve this problem, all assuming that at least one nonnegative value will be entered.
Review each of these code segments, following the same type of reasoning used Parts 1 and 2 of this lab. Indicate in general terms what is true each time through the loop. What is the idea of the loop? If the loop is working toward a goal, how does each iteration of the loop work toward that goal? How would you describe the value stored in variable sum at the start of each iteration of the loop?
For each loop, write a statement of what is true at the beginning of the each time through the loop. Describe what value each variable is supposed to have at the start of each loop iteration. That is, write a loop invariant describing the value each variable should have at the start of each time through the loop.
In considering each of these code segments and loop invariants, which of these code segments will give the correct average when run for any data set (as long as the data begin with a nonnegative number)?
Determine how the flawed code segments above might be corrected.
This laboratory exercise is based on part of an ongoing project of introducing the concepts of assertions and loop invariants informally in CS1 and CS2 courses. Early funding for this work came, in part, from NSF Grant CDA 9214874, "Integrating ObjectOriented Programming and Formal Methods into the Computer Science Curriculum". Henry M. Walker worked as Senior Investigator on this portion of that effort.
This document is available on the World Wide Web as
http://www.cs.grinnell.edu/~walker/courses/153.sp10/labs/labloopinvariants.shtml
created 25 October 2007 last revised 27 February 2010 

For more information, please contact Henry M. Walker at walker@cs.grinnell.edu. 