|
Iteration Case Studies |
||
|
Case Study 1: Count-Controlled Loops Case Study 2: Sentinel-Controlled Loops Case Study 3: Nested Control Structures Case Study 4: Nested Loops |
||
|
Formulating Algorithms: Case Study 1 (Count-Controlled Repetition) Consider the following problem statement: A class of ten students took an exam, with scores (integer) ranging from 1 to 100. Determine the class average. The class average is equal to the sum of the grades divided by the number of students. The algorithm for solving this problem on a computer requires input of each of the grades, calculating the average, and displaying the result. This technique uses a variable called a counter to control the number of times a set of statements should execute. In this example, repetition terminates when the counter exceeds 10.
Lines 170-175 perform the repetition part of the program. While the condition gradeCounter <= 10 is True, the four statements in the loop body are executed. With each iteration of the loop, gradeCounter is incremented by one. Eventually, counter is assigned the value eleven, which causes the loop-continuation test to become False, thus terminating the loop, and displaying the average. Here is the same program using a For loop. Notice that the loop control variable (gradeCounter) does not have to be explicitly initialized or incremented, and that the calculation of the average requires division by gradeCounter minus 1.
|
||
|
Formulating Algorithms with Top-down, Stepwise Refinement: Case Study 2 (Sentinel-Controlled Repetition) Let us generalize a class average problem. Consider the following problem: Develop a class averaging program that will process an arbitrary number of grades each time the program is run. In the statement, no indication is given of how many grades are to be entered. The program must process an arbitrary number of grades. How can the program determine when to stop the input of grades? How will it know when to calculate and display the class average? One way to solve this problem is to use a special value called a sentinel value (also called a signal value, a dummy value, or a flag value) to indicate "end of data entry." The user types grades in until all legitimate grades have been entered. The user then either types the sentinel value to indicate that the last grade has been entered or presses a particular button to indicate that the data entry is complete. Sentinel-controlled repetition is often called indefinite repetition because the number of repetitions is not known before the loop begins executing. Clearly, the sentinel value must be chosen so that it cannot be confused with an acceptable input value. Because grades on an exam are normally nonnegative integers, -1 would be an acceptable sentinel value for this problem. Thus, a run of the class average program might process a stream of inputs such as 95, 96, 75, 74, 89 and -1. The program would then compute and display the class average for the grades 95, 96, 75, 74 and 89 (-1 is the sentinel value, so it should not enter into the averaging calculation). We approach the class average program with a technique called top-down, stepwise refinement, a technique that is essential to the development of well-structured programs. We begin with a pseudocode representation of the top: Determine the class average for the quiz The top is a single statement that conveys the overall function of the program. As such, the top is, in effect, a complete representation of a program. Unfortunately, the top (as in this case) rarely conveys a sufficient amount of detail from which to write the program. So we begin the refinement process. We divide the top into a series of smaller tasks listed in the order in which they need to be performed This results in the following first refinement Initialize variables Here, only the sequence structure has been used--the steps listed are to be executed in order, one after the other. To proceed to the next level of refinement (i.e., the second refinement), we commit to specific variables. We need a running total of the numbers, a count of how many numbers have been processed, a variable to receive the value of each grade as it is input and a variable to hold the calculated average. The pseudocode statement Initialize variables may be refined as follows: Initialize total to zero Notice that only variables total and counter need to be initialized before they are used, the variables average and grade (the calculated average and the user input) need not be initialized because their values will be written over as they are calculated or input. The pseudocode statement Input, sum, and count the exam grades requires a repetition structure (i.e., a loop) that successively inputs each grade. Because we do not know in advance how many grades are to be processed, we will use sentinel-controlled repetition. The user will type legitimate grades in one at a time. After the last legitimate grade is typed, the user will type either the sentinel value or press a button. The program will test for the sentinel value after each grade is input and will terminate the loop when the sentinel value is entered by the user. The second refinement of the preceding pseudocode statement is then Input the first
grade (possibly the sentinel) Notice that in pseudocode, we do not write End While to terminate the body of the repetition structure. At this stage, we need not be concerned about what specific loop will be used. We simply indent all these statements under the While to show that they all belong to the While. The pseudocode statement Calculate and display the class average may be refined as follows: If the counter is not equal to zero Notice that we are being careful here to test for the possibility of division by zero-a fatal logic error that if undetected would cause the program to fail. The complete second refinement of the pseudocode for the class average problem is shown below.
Note the references in the algorithm to a total and a counter. A total is a variable used to accumulate the sum of a series of values. A counter is a variable used to count-in this case, to count the number of grades entered. Variables used to store totals should normally be initialized to 0 before being used in program; otherwise the sum could contain previously stored values (often called garbage values). Although Visual Basic initializes Integer types to 0, it is a good practice to explicitly initialize total variables to 0. Counter variables are normally initialized to zero or one, depending on their use. This algorithm was developed after only two levels of refinement. Sometimes more levels are necessary. The next step is to convert the pseudocode to Visual Basic. The program code is shown below.
Type String is also introduced in this example. A String is a sequence of characters enclosed in a set of double quotes "". Function InputBox is used to input the first grade (line 171). The While provides the repetition by executing the lines gradeTotal += grade The first statement adds the grade and gradeTotal and stores the result into gradeTotal. As each grade is input, gradeCounter is incremented by one. The last line inputs the next grade. The If/Then/Else determines the proper action to take if counter is zero (which occurs if the user enters -1 on line 171). If counter is not zero, the line
is executed. The floating-point division operator, /, is used to get a floating-point result from the division. We do not use the Integer division operator, \, because it returns a whole number (i.e., a number without a decimal place). Despite the fact that floating-point numbers are not always "100% precise," they have numerous applications. For example, when we speak of a "normal" body temperature of 98.6° we do not need to be precise to a large number of digits. When we view the temperature on a thermometer and read it as 98.6°, it may actually be 98.5999473210643°. The point here is that calling this number simply 98.6° is fine for most applications. Another way floating-point numbers develop is through division. When we divide 10 by 3. the result is 3.3333333... with the sequence of 3s repeating infinitely. The computer allocates only a fixed amount of space to bold such a value, so clearly the stored floating-point value can only be an approximation.
|
||
|
Formulating Algorithms with Top-down, Stepwise Refinement: Case Study 3 (Nested Control Structures) In this case study we will see the only other structured way control structures may be combined, namely through nesting of one control structure inside another. Consider the following problem statement:
Your program should analyze the results of the exam as follows:
After reading the problem statement carefully, the following observations can be made (in no particular order):
Let us proceed with top-down, stepwise refinement. We begin with a pseudocode representation of the top. Analyze exam results and decide if a tuition increase is supported Once again, it is important to emphasize that the top is a complete representation of the program, but several refinements are likely to be needed before the pseudocode can be naturally evolved into a program. Our first refinement is Initialize variables Here, too, even though we have a complete representation of the entire program, further refinement is necessary. We now commit to specific variables. Counters are needed to record the passes and failures. A counter (called a loop control variable) controls the looping process and a variable stores the user input. The pseudocode statement Initialize variables may be refined as follows: Initialize
passes to zero The pseudocode statement Input the ten exam grades and count passes and failures requires a loop that inputs the result of each exam. Here it is known in advance that there are ten exam results, so a count-controlled loop is appropriate. Inside each loop (nested within the loop) we can use an If/Then/Else to determine whether each exam result is a pass or fail, and the structure increments the appropriate counter. The refinement of the preceding pseudocode statement is then While student
counter is less than or equal to ten Notice the use of blank lines to set off the If/Else control structure to improve readability. The pseudocode statement Print a summary of the results and decide if tuition should be raised can be refined as follows:
The complete second refinement appears below. Notice that blank lines are used to separate the nested repetition structures for program readability.
The While loop inputs and processes the ten exam results. The If/Then/Else is a nested control structure because it is enclosed within the While. The condition tests if the String variable result is equal to "P", and if so, it increments passes by 1. Otherwise, failures is incremented by 1. Now we convert the pseudocode algorithm to a Visual Basic program. The GUI is shown below, followed by the code. In the code we introduce the Beep statement, which sounds a beep through the computer speaker. Note that a For/Next loop was not used since the loop control variable is not incremented in the case of invalid input.
|
||
|
Formulating Algorithms with Top-down, Stepwise Refinement: Case Study 4 (Nested Loops) In this case study we will see another type of nesting. Consider the following problem statement:
Your program should draw the square as follows:
After reading the problem statement carefully, the following observations can be made (in no particular order):
Let us proceed with top-down, stepwise refinement. We begin with a pseudocode representation of the top. Draw a square of * characters in the command window Once again, it is important to emphasize that the top is a complete representation of the program, but several refinements are likely to be needed before the pseudocode can be naturally evolved into a program. Our first refinement is Initialize variables Here, too, even though we have a complete representation of the entire program, further refinement is necessary. We now commit to specific variables. A variable is needed to store the side, a variable is needed to store the row where printing is occurring, and a variable is needed to store the column where the printing is occurring. The pseudocode statement Initialize variables may be refined as follows: Initialize side to the value input The pseudocode statement Input the side of the square requires that a value be obtained from the user. The pseudocode statement Validate that input is within the proper range may be refined as If side is greater than 0 and less than or equal to 20 then which explicitly tests whether side is greater than 0 and whether side is less than or equal to 20. If the first condition (i.e., side greater than 0) is true, the next condition (i.e., side is less than or equal to 20) is tested. If the first condition is false, the second condition is tested only if you use an AndAlso. The pseudocode statement Print the square can be implemented by using nested loops to draw the square. Here it is known in advance that there are precisely n * characters, so count-controlled repetition is appropriate. One loop will control the row on which each * is drawn. This loop does not do the actual drawing. Inside this loop (i.e., nested within this loop) a second loop will draw each individual *. The refinement of the preceding pseudocode statement is then While row is less than or equal to side While column is less than or equal to side Print After column is set to one, the inner loop executes to completion (i.e. until column exceeds side). Each iteration of the inner loop results in a single * being printed. Print * specifies that the next printing operation is to occur on the row. Variable row is incremented by one. If the outer loop condition allows the body of the loop to be executed, column is reset to one because we want the inner loop to execute again and print another row of * characters. Print specifies that the next printing operation is to occur on the next line. Variable row is incremented by one. This process is repeated until the value of row exceeds side. The complete second refinement appears below. Notice that blank lines are used to separate the nested repetition structures for program readability. Also notice row is initialized after the nested If statements determine that row is valid. This was done for performance reasons-why take the time to initialize rows unless we are going to use rows?
Now we convert the pseudocode algorithm to a Visual Basic program. The GUI is shown below, followed by the output and the code.
|
||