34
CF Q t Chapter Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford 9 Loops A powerful feature of all computer systems is their ability to perform repetitious tasks. Most people dislike monotonous, mechanical jobs that require little thought. Computers have the marvelous property of executing monotonous jobs without tir- ing or complaining. A group of statements that executes repetitively is called a loop. This chapter examines two C++ loop statements—the while statement and the for statement. The while statement while statements are similar to if statements because they both evaluate boolean expressions and execute a statement sequence if the boolean expression is true. The difference between them is that after the statement sequence executes in a while statement, control is automatically transferred back up to the boolean expression for evaluation again. Each time the boolean expression is true, the body executes and the boolean expression is evaluated again. Figure 9.1 shows the owchart for the while statement while (C1) { S1; } The while statement tests condition C1 rst. If C1 is false, it skips statement sequence S1. Otherwise, it executes statement sequence S1 and transfers control up through the collector to the test again. The owchart shows several important properties of the while statement. First, there are two ways to reach the condition C1—from the statement immediately pre- ceding the while statement or from the body of the loop. If C1 is true the rst time, it will be tested again after S1 executes. S1 must eventually do something to change the evaluation of C1. Otherwise, C1 would be true always, and the loop would exe- cute endlessly. Second, Figure 9.1 also shows that it is possible for statement sequence S1 to never execute. It does not execute if C1 is determined to be false the rst time. Figure 9.1 The owchart for the while statement. F T S1 C1

CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

CFQt

Chapter

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

9

Loops

A powerful feature of all computer systems is their ability to perform repetitioustasks. Most people dislike monotonous, mechanical jobs that require little thought.Computers have the marvelous property of executing monotonous jobs without tir-ing or complaining. A group of statements that executes repetitively is called a loop.This chapter examines two C++ loop statements—the

while

statement and the

for

statement.

The while statement

while

statements are similar to

if

statements because they both evaluate booleanexpressions and execute a statement sequence if the boolean expression is true. Thedifference between them is that after the statement sequence executes in a

while

statement, control is automatically transferred back up to the boolean expression forevaluation again. Each time the boolean expression is true, the body executes andthe boolean expression is evaluated again. Figure 9.1 shows the flowchart for the

while

statement

while

(C1)

{

S1;

}

The

while

statement tests condition C1 first. If C1 is false, it skips statementsequence S1. Otherwise, it executes statement sequence S1 and transfers control upthrough the collector to the test again.

The flowchart shows several important properties of the

while

statement. First,there are two ways to reach the condition C1—from the statement immediately pre-ceding the

while

statement or from the body of the loop. If C1 is true the first time,it will be tested again after S1 executes. S1 must eventually do something to changethe evaluation of C1. Otherwise, C1 would be true always, and the loop would exe-cute endlessly. Second, Figure 9.1 also shows that it is possible for statementsequence S1 to never execute. It does not execute if C1 is determined to be false thefirst time.

Figure 9.1The flowchart for the while statement.

F

T

S1

C1

Page 2: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

32

Chapter

9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

The end of file technique

The first program that illustrates the

while

statement computes the sum of a list ofnumbers in the focus window. Each number represents the dollar balance in a cus-tomer’s account. Figure 9.2 shows the input and output for this program. The inputcomes from a QTextEdit object, and the output is displayed on a QLabel object.

Figure 9.2(a) shows a text edit window with three doubles. The user clicks on apush button, which results in the output to the label shown in Figure 9.2(b). The pro-cessing simply consists of adding the real values. To keep the analysis short in thefollowing discussion only three numbers were totaled, but the program worksequally well with any number of values in the text edit. The program in Listing 9.3inputs the data from the text edit and produces the output in the label.

stream

is an object of class

QTextStream

, and scans the text edit for the realvalues. This program uses the standard pattern for establishing the model from thetext edit and linking

input_TextStream

to it.

The statement

sum = 0.0;

initializes variable

sum

to 0.0. Then the statement

input_TextStream >> balance;

scans the first value, which in this example is 54.00. The scan has two effects. First,because the value scanned from the model was 54.00 from the text edit, the effect isthe same as the assignment statement

balance = 54.00;

Second, because there was a value that got scanned, the effect is also the same as theassignment statement

input_TextStream.atEnd = false;

Figure 9.2The input and output of the program in Listing 9.3.

(a) The input window. (b) The output

Page 3: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

The end of file technique

33

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

// Project Chap09B, File main.cpp#include <iostream>using namespace std;

int main() {double sum = 0.0, balance = 0.0;cout << “Enter a balance, or <control-D> to quit: “;cin >> balance;while (!cin.eof()) {

if (cin.fail()) {cout << “Corrupt data encountered. Try again.\n” ;return 1;

}sum += balance;cout << “Enter a balance, or <control-D> to quit: “;cin >> balance;

}cout.width(1); cout.precision(2); cout.setf(ios::fixed | ios::showpoint);cout << “\nThe total is $” << sum << “.” << endl;return 0;

}

// Project Chap09B, File MainWindow.cpp#include “MainWindow.h”

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent) { setupUi(this);}

void MainWindow::on_sumPushButton_clicked() {QString text = guiTextEdit->toPlainText();QTextStream textStream(&text);double sum = 0.0, balance = 0.0;while (!textStream.atEnd()) {

textStream >> balance;if (textStream.status() == QTextStream::ReadCorruptData) {

outLabel->setText(“Corrupt data encountered. Try again”);return;

}sum += balance;

}outLabel->setText(QString(“The total is $%1.”).arg(sum, 1, ‘f’, 2));

}

void MainWindow::on_clearPushButton_clicked() {guiTextEdit->clear();outLabel->clear();

}

Figure 9.3A command line program to find the total of a series of data values input by the user. It uses the eof technique.

Figure 9.4A Qt program to find the total of a series of data values input by the user. It uses the eof technique.

Page 4: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

34

Chapter

9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

The next statement to execute is

while (!stream.atEnd()) {

Because

stream.atEnd()

is false,

!stream.atEnd()

is true, and the body ofthe loop executes. The first statement in the statement sequence of the

while

body is

sum += balance;

giving 0.0 + 54.0 to

sum

. The second statement in the statement sequence of the

while

is

stream >> balance;

which scans the next group of characters in the text, giving

balance

the value of20.40 and

stream.atEnd()

the value of false.Now, control returns back to the test of the

while

loop, which is still true. So, thestatement sequence executes again. The assignment statement gives

sum

the value of54.0 + 20.4, which is 74.4. The

stream >> balance

statement gives

balance

thevalue of 76.5 and

stream.atEnd()

the value of false.Control again returns back to the test of the

while

loop, which is true again. So,the statement sequence executes once more. The assignment statement gives

sum

thevalue of 74.4 + 76.5, which is 150.9. This time the

stream >> balance

statementgives

stream.atEnd()

the value true because there is no more visible text after theposition of the stream.

When control returns back to the test of the

while

loop, the condition is false, sothe loop terminates, and the statements following the loop block execute. They con-vert the real value of

sum

to a corresponding QString value output the result to thelabel.

Execution counts

As consumers, we are familiar with the process of evaluating products. When youchoose between two automobiles to purchase, what factors influence your choice?For some people, speed and road handling may be the most important factors. Oth-ers may care about fuel economy. Some may be looking for luxury and a smoothride. Most people are also concerned about price. These factors usually competewith one another in the car buyer’s mind. A car with much power and speed typi-cally does not have good fuel economy. One that is luxurious does not come with alow price. In design terminology, that is a trade-off. The buyer may wish to trade offfuel economy to gain speed and power.

The same type of problem emerges when we evaluate algorithms. Several com-peting factors are present. Usually, a gain of one property in an algorithm comes atthe expense of another. Two important properties of an algorithm are the memoryspace required to store the program and its data, and the time necessary to executethe program. To compare several different algorithms that perform the same compu-tation, we need a method of assessing these two properties. The following discus-sion presents a method for estimating the time necessary to execute a program.

The space/time trade-off

Page 5: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Execution counts

35

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

One way to estimate the time necessary for an algorithm to execute is to count thenumber of statements that execute. If an algorithm has no

if

statements or loops,then the number of statements that execute is simply the number of executable state-ments in the program listing.

If the algorithm has a loop, however, the number of statements in the listing is notequal to the number of statements executed. This is because the statements in thebody may execute many times, even though they appear only once in the programlisting.

Function

on_guiPushButton_clicked

has 8 executable statements shownbelow. The declarations in the variable declaration part are not executable. Neitherare

{

nor }.

Page 6: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

36

Chapter

9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

Even though the listing contains 8 executable statements, more than 8 statementsexecute. Statements

(5)

and

(6)

are part of a loop and may execute more than once.For the three real values in the text edit, statement (4) executes four times, and state-ments (5) and (6) each execute three times, as shown by the trace below.

So, the total number of executions is one each for statements

(1)

,

(2)

,

(3)

, and

(8)

for a total of four, plus four for statement (4), plus three each for statements

(5)

and

(6)

for a total of six. The grand total is therefore four plus four plus six, which is 14statements executed.

If there were no data values in the focus window, then the trace would be asshown below, and 10 statements would execute.

Statementnumber Executable statement

(1)

QString text = guiTextEdit->toPlainText();

(2)

QTextStream stream(&text);

(3) double sum = 0.0, balance = 0.0;(4) while (!stream.atEnd()) {(5) stream >> balance;(6) sum += balance(7) }(8) outLabel->setText(QString(“...”).arg(...));

Statementexecuted sum balance atEnd() label(1)(2) false(3) 0.0 0.0 false(4) 0.0 0.0 false(5) 0.0 54.0 false(6) 54.0 54.0 false(4) 54.0 54.0 false(5) 54.0 20.4 false(6) 74.4 20.4 false(4) 74.4 20.4 false(5) 74.4 76.5 true(6) 150.9 76.5 true(4) 150.9 76.5 true(8) 150.9 76.5 true “150.90”

Statementexecuted sum balance atEnd() label(1)(2)(3) 0.0 0.0 true(4) 0.0 0.0 true(8) 0.0 0.0 true “0.0”

The executable statements of procedure ComputeTotal

A trace of procedure ComputeTotal with three data values in the focus window

A trace of procedure ComputeTotal with no data values in the focus window

Page 7: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Execution time estimates 37

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

If the text edit contained n data values, then a total of statements wouldexecute as shown in Figure 9.5.

Execution time estimatesYou can use the general expression for the statement count, , to estimate theexecution time for a large number of data values, given the execution time for asmall number of data values.

Example 9.1 Suppose you execute procedure ComputeTotal with 100 data valuesand it takes 140 µs (140 microseconds, which is seconds). The problemis to estimate how long it would take to execute the program with 1000 data values.

Assuming that each executable statement takes the same amount of time to execute,simply form the ratio

where T is the time to execute with 1000 data values. Solving for T gives

or . !

The time of 0.001379 seconds is only an estimate. Each statement in procedureComputeTotal does not execute in the same amount of time. Remember that thecompiler must translate the C++ source statements to object statements in machinelanguage before it can execute. Typically, the compiler translates one source state-ment to more than one object statement. It may translate one source statement intothree object statements and another source statement into five object statements.Furthermore, even the object statements do not execute in equal amounts of time.

Statement No datavalues

Three datavalues

n datavalues

(1) 1 1 1(2) 1 1 1(3) 1 1 1(4) 1 4 n + 1(5) 0 3 n(6) 0 3 n(7) 0 0 0(8) 1 1 1

Total: 5 14 3n + 5

3n 10+

Figure 9.5Statement execution count for the procedure ComputeTotal in Figure 9.3.

3n 5+

140 10 6–×

1403 100× 5+--------------------------- T

3 1000× 5+------------------------------=

140305--------- T

3005------------=

T 1379 µs 0.001379 s= =

Page 8: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

38 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

Under these circumstances, it is unreasonable to expect each source instruction toexecute in the same amount of time.

The following example shows why the estimate works so well in practice. Indealing with large numbers of data, say hundreds or thousands for the value of n, theadditive constants are insignificant to the final result and can be ignored.

Example 9.2 In the previous example, ignoring the additive constant, 10, in theexpression can be justified because 305 is about equal to 300, and 3005 is aboutequal to 3000. Assuming that is approximately equal to , forming theratio and solving for T then yields

or , which is not too different from our original esti-mate.

Notice that when you ignore the additive constant, the coefficient of n, which is 3,cancels in the ratio. Why is the coefficient of n unimportant in the estimate of theexecution time for 1000 data values? Because for these large amounts of data,namely n = 100 and n = 1000, the number of statements executed is just aboutdirectly proportional to n. That implies that doubling the number of data values willdouble the number of statements executed, hence it will double the execution time.Or, as in this problem, multiplying the number of data values by 10 multiplies theexecution time by 10.

Although the coefficient of n is unimportant in estimating the execution time forone algorithm with different amounts of data, it is important in comparing two dif-ferent algorithms for the same job. If one algorithm requires 4n + 5 statements toexecute, and another algorithm to do the same processing requires 7n + 5 statementsto execute, the first will execute faster than the second with the same amount of data.

Loop invariantsA loop invariant is an assertion at the beginning of a loop. Because it is an assertion,it is a statement that is true at a specific point in a program. Figure 9.6 shows thepoint at which a loop invariant is true.You can see from Figure 9.6(a) that there are two ways to get to the loop invariant.You can get to it from above by executing the statement sequence S1, or you can getto it from below by executing the statement sequence S2 in the body of the loop.

In the program of Figure 9.3, the statement sequence S1 is

QTextStream stream(&text);sum = 0.0;

the condition C1 is

3n 5+ 3n

1403 100×------------------ T

3 1000×---------------------=

140100--------- T

1000------------=

T 1400 µs 0.00140 s= =!

Estimating the execution time by ignoring the additive constant and the coefficients

Page 9: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Loop invariants 39

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

!stream.atEnd()

and the statement sequence S2 is

stream >> balance;sum += balance;

For this program, the loop invariant is" sum is the total of all the values scanned, including the current value of bal-

ance.To prove that a statement is a loop invariant, you must show two things:

" The statement is true initially because of the execution of S1." The statement is true at the end of each loop because of the execution of S2.

Consider what must be the case when a WHILE loop eventually terminates." The loop invariant is true." The loop condition is false.

The loop condition must be false, because that is the only way the loop can termi-nate. For the program of Figure 9.3, you know that after the loop terminates sum isthe total of all the values scanned, and that stream.atEnd() is true.

This algorithm illustrates a common programming technique. Generally, whenyou program with loops, you should try to formulate a useful loop invariant. Estab-lish the invariant before the loop executes the first time. Then, design the body of theloop so that each time it executes, the loop invariant becomes true when you reachthe condition at the top of the loop from below. That is, you must write the body ofthe loop in such a way to reestablish the loop invariant.

(a) Flowchart. (b) Source code.

Figure 9.6The location of the loop invariant for a WHILE loop.

F

T

S2

C1

Location of loop invariant

S1

Statement 1(* Location of loop invariant *)(* Loop invariant is true. *)while (Condition1) {

Statement2}(* Loop invariant is true and Condition1 is false. *)

The loop invariant for Figure 9.3

Proving a loop invariant

When a WHILE loop terminates

Using loop invariants

Page 10: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

40 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

The concept of a loop invariant may seem like much ado about nothing, or it mayseem to be making a complicated point about something that appears simple. Usingloop invariants to design programs is frequently a useful design technique that youwill find aids in reasoning about your loops. !

Computing the averageSuppose you want to compute the average of the balances in the accounts. Youwould need not only their sum, but the number of accounts as well. The algorithm inFigure 9.7 uses another integer variable, numAccts, to count how many data valuesare in a string. This string of real values may be retrieved from either a text edit or atext file.

int numAccts = 0;QTextStream stream(&text);while (!stream.atEnd()) {

stream >> balance; sum += balance;

numAccts++;}if (numAccts > 0) {

Output sum / numAccts} else {

Output a no accounts message}

This algorithm illustrates a common programming technique. To determine howmany times a loop executes, initialize a counting variable, in this algorithm num-Accts, outside the loop to zero. Each time you scan a real value in the statementsequence of the loop, increment the counting variable by one. When the loop termi-nates, the value of the counting variable will be the number of values scanned by theloop. Before dividing by numAccts to compute the average, you must test to makesure that it is not zero. Otherwise your program may attempt a division by zero,which would cause a program trap by your user.

Finding the largestThe algorithm in Figure 9.8 finds the largest number from a string that contains inte-ger values. If the input in the string is

73 80 -18 68 92 75

then the output is 92.

The two variables, num and largest, are integers. The algorithm works by scan-ning the first value from the text stream into num. If the text stream is empty theboolean my_TextStream.atEnd() will be set to true. In that case, the algorithm out-puts a message indicating that the input string is empty.

Figure 9.7An algorithm to find the average of all the data values in a string.

Page 11: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Double Expressions 41

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

QTextStream stream(&text);if (stream.atEnd()) {Output empty string message

} else {stream >> largest;while (!steam.atEnd()) {

stream >> num;if (num > largest) {

largest = num;}

}Output largest

}

The loop invariant is" largest has the largest of all the values scanned including the current value

of num.Can you see that this loop invariant is true just before the loop executes even for thefirst time?

The second time through the loop, the true alternative of the IF statement doesnot execute, because the value of num, which is now –18, is not greater than thevalue of largest, which is 80. Had the value of num been greater than 80, largestwould have acquired that value and would still be the largest number scanned thusfar. When the loop terminates the loop invariant will still be true. That is, variablelargest has the largest value scanned so far, except for the last value scanned intovariable num.

This algorithm illustrates a common programming technique. To save a valuethrough successive loop iterations, declare a variable and initialize it appropriately.In the body of the loop, update the value with an assignment statement in the alter-native of an if statement as needed.

Double ExpressionsYou must be careful when you test real expressions in while statements. Unlikeinteger values, double values have fractional parts, which the computer can storeonly approximately in main memory. The approximate nature of real values cancause endless loops if you do not design your while tests properly.

Example 9.3 The following code fragment is an endless loop:

double r = 0.6;while (r != 1.0) {

r += 0.1;}

It would seem that after r is initialized to 0.6, the loop would increase it to 0.7, 0.8,0.9, and 1.0, at which point the loop would terminate. The problem is that r is neverexactly 1.0 after those calculations. After four executions of the loop the value of rwill be approximately one, not exactly one. !

Figure 9.8An algorithm to find the largest value in a string.

The loop invariant for Figure 9.8

Double values are

Page 12: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

42 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

The problem in Example 9.3 is that r was tested for strict inequality. In general,you should use the following rule for testing real values:

" Never test a real expression for strict equality, ==, or strict inequality, !=.Tests for real values should always contain a less than or a greater than part.

Example 9.4 The previous example could be coded

double r = 0.6;while (r <= 0.95) {

r += 0.1;}

which would increase r to 0.7, 0.8, 0.9, and 1.0, at which point the loop would ter-minate.

The C++ language does not have an operator that raises a value to a power. How-ever, the cmath library module has the function

double pow (double, double);

For example, the expression where x is a double variable can be written

7 * pow(x, 3)

Without the function, the expression would be written 7 * x * x * x, whichrequires three multiplications. With the function, three multiplications are necessaryinside the function itself. Multiplication of real values is one of the most time-con-suming operations that the CPU can do. Polynomial expressions, which are sums ofterms such as , are especially time consuming when they occur in loops thatexecute repeatedly. A common technique to minimize the computation time is tocompletely factor such expressions to reduce the number of real multiplicationsrequired. This technique will be used in the program in Figure 9.13.

Example 9.5 Suppose you need to evaluate . Without factor-ing, the corresponding C++ expression is

7 * x * x * x + 2 * x * x + 8 * x + 5

which requires six multiplications and three additions. On the other hand, if youcompletely factor the expression as then the correspondingC++ expression is

((7 * x + 2) * x + 8) * x + 5

which requires only three multiplications and three additions. !

!

Minimizing the number of multiplications

7x3

7x3

7x3 2x2 8x 5+ + +

7x 2+( )x 8+( )x 5+

Page 13: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

The bisection algorithm 43

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

The bisection algorithmA numerical method is an algorithm that calculates a value or set of values thatapproximates the solution of a mathematical problem. The program in Figure 9.13 isa numerical method that computes one root of the cubic equation

with the bisection algorithm.Figure 9.9 is a graph of the function . The roots of the

cubic equation are the values of x for which . Figure 9.9 shows that is zero for three different values of x: (a) between –2.0 and –1.0, (b) between 0.0 and1.0, and (c) between 2.0 and 3.0. Although this cubic equation has three roots, cubicequations in general can have from one to three roots. The program will determinethe root of the equation that lies between and .

In the bisection algorithm, the variable left is a value of x that lies to the left ofthe root and the variable right is a value of x that lies to the right of the root. Thisalgorithm initializes left to 2.0 and right to 3.0. Then, as Figure 9.10(a) shows, itcalculates the variable fLeft as

fLeft = f(left)

The next step is to compute the value of x that is the midpoint between left andright. As Figure 9.10(b) shows, the algorithm gives that value of x to the variablemid and computes fMid as

fMid = f(mid)

The value of fMid determines whether the root lies to the left or right of mid. IffLeft and fMid have the same sign, then the root lies to the right of mid. Otherwise,the root lies to the left of mid. In the figure, fLeft and fMid have the same sign,because both are negative. Therefore, the root lies to the right of mid.

If the root lies to the right of mid, the algorithm changes the value of left andfLeft by

left = midfLeft = fMid

x3 x2– 4x 2+– 0=f x( ) x3 x2– 4x– 2+=

Figure 9.9A graph of the function

f x( ) x3 x2– 4x– 2+=

f x( ) 0= f x( )

x 2= x 3=

(a) Before the loop executes the first time.

(b) Computation of mid and fMid. (c) Updating left and fLeft.

left

fLeft

right left

fLeft

rightmid

fMid

rightleft

fLeft

Page 14: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

44 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

as Figure 9.10(c) shows. The root is still between left and right. Had the root lainto the left of mid, the algorithm would have changed the value of right by

right = mid

so that the root would still be between left and right.The bisection algorithm continues to find the midpoint between left and right.

Each time it updates left or right, it decreases the interval between them such thatthe root is still in the interval. The loop invariant is the assertion that the root isbetween left and right. The loop terminates when left and right get closeenough to satisfy a tolerance limit set by the user.

Figure 9.11 shows three executions of a program that implements the bisectionalgorithm. When the user enters 0.1, the bisection method calculates the root as2.34375. It is accurate to the nearest tenth, so the last four digits, 4375, may not besignificant. When the user enters 0.01, the loop executes more times and calculatesthe root as 2.33984375, a more accurate value for the root than 2.34375. The smallerthe tolerance, the more times the loop executes and the more accurate is the valuefor the root. But then the program runs longer. So there is a trade-off between theaccuracy of the solution and the execution time.

Slot on_guiPushButton_clicked() in Listing 9.13 implements the bisectionalgorithm in C++. The double value for the tolerance entered by the user is stored intolerance. As long as the length of the interval is greater than the tolerance enteredby the user, the loop executes. Each time the loop executes, the program halves theinterval, which guarantees that the loop will eventually terminate.

If the user enters zero for the tolerance, the loop will execute endlessly, becausecontinually halving the interval never permits it to reach zero. If the user enters anegative tolerance, the loop will execute endlessly because the boolean expressionin the while statement will always be true. The program could be improved by test-ing the tolerance for negative or zero values and not allowing them.

Figure 9.10The bisection algorithm to find a root of f(x).

The loop invariant for the bisection algorithm

Figure 9.11Three executions of the bisection algorithm of Listing 9.13.

Page 15: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Stepwise refinement 45

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

// Project Chap09C, Program MainWindow.h#include “ui_Chap09C.h”#include <cmath>

class MainWindow : public QMainWindow, private Ui::MainWindow { Q_OBJECT

public: MainWindow(QMainWindow *parent = 0);

private slots:void on_guiPushButton_clicked();

};

// Project Chap09C, Program MainWindow.cpp#include “MainWindow.h”

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent) {setupUi(this);}

void MainWindow::on_guiPushButton_clicked() {const double A3 = 1.0, A2 = -1.0, A1 = -4.0, A0 = 2.0;double tolerance = toleranceDoubleSpinBox->value();double left = 2.0;double fLeft = ((A3 * left + A2) * left + A1) * left + A0;double right = 3.0;double mid = (left + right) / 2.0;double fMid;// Assert: A root is between left and rightwhile (fabs(left - right) > tolerance) { mid = (left + right) / 2.0; fMid = ((A3 * mid + A2) * mid + A1) * mid + A0;

if (fLeft * fMid > 0.0) { // Assert: A root is between mid and right

left = mid;fLeft = fMid;

} else { // Assert: A root is between left and mid

right = mid;}

}outLabel->setText(QString(“The root is %1”).arg(mid, 1, ‘f’, 16));

}

Stepwise refinementThe next example of the while loop illustrates a software development techniqueknown as stepwise refinement. The data for this problem consists of a focus window

Figure 9.12The header file for the bisection algorithm.

Figure 9.13The implementation file for the bisection algorithm.

Page 16: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

46 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

containing an employee ID number followed by two real values that represent thenumber of hours worked per week and the hourly pay rate for that employee. Theprogram must output to the Log a table with the employee ID number, hoursworked, and weekly pay with the possibility of overtime. It must also determine theaverage salary of all the employees as well as the number of employees who earnedovertime. For example, if the text edit contains the text

123-A6002 35.0 13.00123-A6517 45.0 10.00561-B3882 40.0 12.50561-B4559 40.0 11.00561-B7384 50.0 10.00

then the output to the Log should be

123-A6002 35.0 455.00123-A6517 45.0 475.00561-B3882 40.0 500.00561-B4559 40.0 440.00561-B7384 50.0 550.00Average wages: 484.00Number with overtime: 2

Stepwise refinement is based on the concept of abstraction. The idea is to not beconcerned with all the details that are necessary for the final C++ program, butinstead to focus on the logic at a higher level of abstraction. The process consists ofa number of steps or passes at the problem. At each pass, you get to a lower level ofabstraction until you reach the final pass which produces the complete program.What follows is a description of the passes for a stepwise refinement solution for theabove problem.

The first step is to determine the variables needed to solve the problem. Remem-ber that input, processing, and output are the three major parts of a program. Thatgives a hint of the variables required.

Input—The input consists of a sequence of lines, each one of which contains astring and two real values. Hence you will need a QString, say empID, and two realvariables, say hours and rate, for the input. You will need a QTextStreaminput_TextStream to input their values.

Processing—To compute the average, you must compute each wage and dividethe total wages by the number of employees. Hence you will need real variables,wages and totalWages, to store the computed wage for an individual and for thetotal of all the wages. An integer variable, numEmp, will count the number of employ-ees. The integer variable numOvertime will keep track of the number of employeeswho worked overtime.

Output—The three variables, hours, rate, and wages, will be used to output asingle line in the report. aveWages will be a real variable for outputting the averagewage at the bottom of the report. The value of numOvertime will also appear at thebottom.

The tentative variable declaration part now looks like this:

Page 17: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Stepwise refinement 47

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

QTexetStream stream(&text);QString empID;double hours, rate;double wages, totalWages, aveWages;int numEmp, numOvertime;

In this problem, the number of variables and their types were fairly easy to deter-mine before writing the logic of the program. With some problems it is not alwayspossible to determine the variables beforehand. In general, you should determine theprincipal variables of the program at an early stage of the stepwise refinement. Then,augment the variable declaration part with new variables as refinement progresses.

First pass—The program in Figure 9.3 showed the technique of processing a setof values using the eot technique. The coding pattern is to perform a scan before theloop. In the body of the loop, process the data that was just read. After processing,scan the model for the next values as the last statements in the loop. Using this pat-tern, the first pass is the following:

Initialize variablesInput empID, hours, ratewhile (!stream.atEnd()) {

Process empID, hours, rateInput empID, hours, rate

}Compute the averageOutput aveWages, numOvertime

Second pass—Each pass in a stepwise refinement solution should concentrate onone aspect of the problem. This problem requires a table with a list of values andsummary information at the bottom. The second pass will solve the table output partof the problem. Two kinds of lines appear in the body of the report, one for thosewho worked overtime and one for those who did not. This requires an IF statementin the body of the loop. The summary information appears once at the bottom of thereport. The output statements for the summary must therefore be after the END of theWHILE loop. Here is the second pass:

Initialize variablesInput empID, hours, ratewhile (!stream.atEnd()) {

if (employee did not work overtime) {Compute wages without overtime

} else {Compute wages with overtime

}Output empID, hours, wagesInput empID, hours, rate

}Compute the averageOutput aveWages, numOvertime

Page 18: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

48 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

Third pass—This pass will solve the problem of computing the average and thenumber who worked overtime. The average is the sum of the wages divided by thenumber of employees. You can compute the sum by the technique of Figure 9.7.That example initialized the variable sum to 0.00 before the while loop. Each timethe loop executed, sum increased by the value input from the file. In this problem,you can initialize and increase totalWages the same way.

You can compute the number of employees using numEmp as a counting variable.Initialize numEmp to zero before the while loop. Each time the body of the loop exe-cutes, increment numEmp by one. After the loop has terminated, the value of numEmpwill equal the number of times the loop was executed, which equals the number oftimes a line was processed, which equals the number of employees.

Similarly, you can initialize numOvertime to zero before the loop. But now youonly want to increment numOvertime by one if the employee worked overtime. Thethird pass is

totalWages = 0.0;numEmp = 0;numOvertime = 0;while (!stream.atEnd()) {

Input empID, hours, rateif (employee did not work overtime) {

wages = hours * rate;} else {

wages = 40.0 * rate + (hours - 40.0) * 1.5 * rate;numOvertime++;

}totalWages = totalWages + wages;numEmp++;Output empID, hours, wages

}if (numEmp > 0) {

aveWages = totalWages / numEmp;} else {

aveWages = 0.00;}Output aveWages, numOvertime

Fourth Pass—This pass is the complete C++ program shown in Figure 9.14.This program shows several common stepwise refinement characteristics. In

every pass except the last one, all the irrelevant details of input and output should besuppressed. The first three passes of this example used the pseudocode statementsInput and Output. Only on the last pass were they converted to C++ scans and QTex-tEdit functions with formatting details.

// Project Chap09D, File MainWindow.cpp#include “MainWindow.h”

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent) {

Figure 9.14The implementation file for the bisection algorithm.

Page 19: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Stepwise refinement 49

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

setupUi(this);fileName = ““;

}

void MainWindow::on_actionOpen_activated() {fileName = QFileDialog::getOpenFileName(

this, “Choose a directory for opening”, “.”);QFile file(fileName);file.open(QIODevice::ReadOnly);QTextStream textStream(&file);guiTextEdit->setPlainText(textStream.readAll());file.close();

}

void MainWindow::on_actionSave_As_activated() {fileName = QFileDialog::getSaveFileName(

this, “Choose a directory for saving”, “.”);QFile file(fileName);file.open(QIODevice::WriteOnly);QTextStream textStream(&file);textStream << guiTextEdit->toPlainText();file.close();

}

void MainWindow::on_actionSave_activated() {if (fileName == ““) {

fileName = QFileDialog::getSaveFileName(this, “Choose a directory for saving”, “.”);

}QFile file(fileName);file.open(QIODevice::WriteOnly);QTextStream textStream(&file);textStream << guiTextEdit->toPlainText();file.close();

}

void MainWindow::on_summarizePushButton_clicked() {guiTextBrowser->clear();

QString text = guiTextEdit->toPlainText();QTextStream textStream(&text);QString id;double hours = 0.0, rate = 0.0, average = 0.0, wage = 0.0, totalWages = 0.0;int numEmployees = 0, numOverTimes = 0;while (!textStream.atEnd()) {

textStream >> id;if (textStream.status() == QTextStream::ReadCorruptData) {

guiTextBrowser->setPlainText(“Error while reading an id entry.”);return;

}textStream >> hours;if (textStream.status() == QTextStream::ReadCorruptData) {

guiTextBrowser->setPlainText(“Error while reading an hours entry.”);

Page 20: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

50 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

return;}textStream >> rate;if (textStream.status() == QTextStream::ReadCorruptData) {

guiTextBrowser->setPlainText(“Error while reading a rate entry.”);return;

}if (hours <= 40) {

wage = hours * rate;} else {

wage = 40.0 * rate + (hours - 40) * 1.5 * rate;numOverTimes++;

}totalWages += wage;numEmployees++;guiTextBrowser->insertPlainText(

QString(“%1%2%3\n”) .arg(id) .arg(hours, 10, ‘f’, 1)

.arg(wage, 10, ‘f’, 1)); }average = (numEmployees > 0) ? totalWages / numEmployees : 0.0;guiTextBrowser->insertPlainText(

QString(“\nAverage wages: %1\nNumber with overtime: %2”).arg(average, 1, ‘f’, 2).arg(numOverTimes));

}

Each pass should isolate and solve one specific part of the problem. In this pro-gram, the parts solved by each pass were the following:

" First pass input from the focus window" Second pass output of the table" Third pass computation of summary values" Fourth pass C++/Qt details

The strategy here is to divide and conquer. If you have a large problem that you donot know how to solve, divide it into smaller subproblems that you can solve. Step-wise refinement gives you a framework for dividing a problem into smaller parts.

Another tip with stepwise refinement is to work it out on your text editor, not onpaper. With each pass you can expand one pseudocode statement into several state-ments that are closer to C++, a job more easily accomplished on a screen than on apiece of paper. At the end of the last pass, the C++ program will be on your diskready to compile.

The structured programming theoremC++ provides several loop statements other than the while statement, one of whichis the for statement. Theoretically, there is no reason to provide any loop other thanthe while. An important computer science theorem about the power of the while

Page 21: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

The for statement 51

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

statement coupled with the if statement is known as the structured programmingtheorem, proved by Corrado Bohm and Guiseppe Jacopini in 1966. They provedmathematically that any algorithm, no matter how large or complicated, can be writ-ten with only three control statements—sequence, which is one statement followinganother, the if statement, and the while statement.

According to the structured programming theorem, C++ really does not need toprovide the switch statement, for example. You can imagine that any program witha switch statement could be written to perform the identical processing using an ifstatement with several else if parts. By the same token, any program with a forstatement can be written to perform the identical processing using a while state-ment. Nevertheless, statements like switch and for are provided, not because ofany additional power they give to the programmer, but because they are convenient.

The for statementSuppose you want to compute the sum of all the integers from 1 to 100. You coulduse a while loop, as in Figure 9.15. sum and i are variables of type int. i is calledthe control variable of the loop because its value controls when the loop terminates.

sum = 0;i = 1;while (i <= 100) {

sum += i++;}Output sum

If you execute the above algorithm, it will output 5050, which is the sum.

The sequence of steps" Initialize a variable." Test the variable at the beginning of a loop." Execute the body of the loop." Increment the variable.

occurs frequently in programs. The for statement automatically initializes a controlvariable, tests it at the beginning of the loop, and increments it after executing thebody of the loop. The program in Listing 9.16 is the above algorithm written in C++.It finds the sum of consecutive integers between one and an ending value entered bythe user, but it is written with a for loop in place of the while loop. Figure 9.17shows the dialog box for this program.

When slot on_guiPushButton_clicked() executes, sum gets 0. Then, the state-ment

for (int i = 1; i <= num; i++) {

executes. The word for is a C++ reserved word. The assignment statement beforethe first semicolon gives an initial value to the control variable of the for statement.In this statement, i, the control variable, gets the initial value of 1.

The structured programming theorem was proved by Bohm and Jacopini.

Figure 9.15An algorithm for the sum of consecutive integers with a while loop.

1 2 3 … 100+ + + +

Page 22: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

52 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

The for statement then compares the current value of i with the expressionbefore the second semicolon. If the value of the control variable is greater than theexpression, the loop terminates. Otherwise, the loop body executes. In this state-ment, the value of the control variable, 1, is not greater than the value of the expres-sion, 100. The loop body executes, which adds 1 to sum.

Control returns to the top of the loop. The for statement automatically incre-ments the value of i according to its third expression, i++. It then compares thevalue of i with its second expression. Because the current value of i, which is 2, isnot greater than the value of the expression, which is 100, the body of the loop exe-cutes again. The loop continues executing, with i getting the values 1, 2, 3, and soon, to 100. After it executes with i having the value 100, the loop terminates.

// Project Chap09E, File MainWindow.cpp#include “MainWindow.h”

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent) { setupUi(this);}

void MainWindow::on_guiPushButton_clicked() {int sum = 0;int n = numSpinBox->value();for (int i = 0; i <= n; i++) {

sum += i;}outLabel->setText(QString(“The sum from 1 to %1 is %2.”).arg(n).arg(sum));

}

You should be able to determine the statement execution count for this program.A total of statements execute, where n is the value input for n. That is

, or 207 statement executions for the computation of the sum of the first100 integers.

The algorithm of Figure 9.16 may be a good illustration of the FOR statement, butit is not a good solution to the problem. The formula, , gives the sum ofthe first m integers directly, as will be shown later. The following simpler algorithmsolves the same problem. Assuming that the Output statement requires the same fivestatements as in Figure 9.16, this algorithm requires only six statement executionsregardless of the value input for d.num.

...sum = n * (n + 1) / 2;...

#$The guarded command do statementThe statement that corresponds to the C++ while statement is the do statement inGCL. As with the if statement, the do statement uses a guarded command. The C++

Figure 9.16Computing the sum of the first d.num integers with a FOR loop.

Figure 9.17The dialog box for the program of Figure 9.16.

2n 7+2 100( ) 7+

m m 1+( ) 2

Figure 9.18A better algorithm for the sum of consecutive integers.

Page 23: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Exercises 53

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

statement

while (C1) {S1;

}

is written in GCL as

do od

Example 9.6 The algorithm of Figure 9.7 to find the average is written in GCL as

s := 0.0; nA := 0; sc.ScanR(b);do s := s + b; nA := nA + 1; sc.ScanR(b) odif

fi !

Exercises

1. (a) What is a loop invariant? (b) What two things must you show to prove that a state-ment is a loop invariant? (c) What must be the case when a while loop terminates?

2. For the algorithm in Figure 9.7 that computes the average of the accounts do the fol-lowing: (a) Draw a flowchart. (b) Determine the total statement execution count ifthere are three data values. Include only the statements in the figure and ignore anystatements that would be in a complete C++ procedure. (c) Determine the total state-ment execution count if there are n data values. (d) If the algorithm executes in 50 µsfor 200 data values, estimate the execution time for 10,000 data values from (c). Useboth the exact computation and the approximate computation and compare how closethey are by computing their percentage difference.

3. For the algorithm in Figure 9.8 that finds the largest value, do the following: (a) Draw aflowchart. (b) Determine the total statement execution count if there are three data val-ues. Include only the statements in the figure and ignore any statements that would bein a complete C++ function. (c) Determine the total statement execution count if thereare n data values, assuming that the body of the nested if statement executes everytime. This is called the “worst case” time. (d) Determine the execution count assumingthat the first number in the list is the largest. This is called the “best case” time. (e) Ifthe algorithm executes in 120 µs for 80 data values, estimate the execution time for5000 data values assuming the count in part (c). Use the exact computation. (f) Workpart (e) assuming the count in part (d). (g) Give the percentage difference between theworst case and the best case times.

4. State the loop invariant for the while loop in function on_guiPushButton_clickedin Figure 9.3. The loop invariant will be a statement about the state of sum.

5. State the loop invariant for the while loop in the algorithm to compute the average inFigure 9.7. The loop invariant will include statements about the states of both sum andnumAccts.

C1 S1!

sc.eot¬ !nA 0> Output s nA!

[] nA 0" Output a no accounts message!

Page 24: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

54 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

6. Tell how many multiplication and addition steps are required to evaluate

Factor the expression so that it requires only four multiplication and four additionsteps.

7. Determine the output to the Log of the code fragment.

sum = 0;while (i < 9) {

sum += i;i++;

}cout << "sum = " << sum << endl;

for the following initial values of i.

(a) 5 (b) 8 (c) 9 (d) 0

8. Answer these questions for each of the C++ code fragments. (1) What is the first valueadded to sum? (2) What is the last value added to sum? (3) What is the value of a at thetermination of the loop? (4) How many times does the body of the loop execute?

(a) (b) (c)sum = 0; sum = 0; sum = 0;a = 50; a = 50; a = 50;while (a < 100) { while (a < 100) { while (a <= 100) {

a += 2; sum += a; a += 2;sum += a; a += 2; sum += a;

} } }

9. What is the value of count after the statements are executed?

i = 15;count = 0;while (i <= 1000) {

i += 2);count++;

}

10. Determine the output to the terminal of the following code fragment.

sum = 0;for (i = 5; i <= num; i++) {

sum += i;}cout << "sum = " << sum << endl;

for the following values of num.

(a) 10 (b) 6 (c) 5 (d) 4

11. Determine the total statement execution count of the code fragment in the previous

ax4 bx3 cx2 dx e+ + + +

Page 25: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Problems 55

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

exercise if num has the value n. Assume that n is greater than or equal to 5.

12. Determine the output of the following code fragment.

sum = 0;for (i = 10; i <= num; i--) {

sum += i;}cout << "sum = " << sum << endl;

for the following values of num.

(a) 5 (b) 9 (c) 10 (d) 11

13. If slot on_guiPushButton_clicked in Figure 9.16 takes 40 µs to execute when numhas the value of 100, how long does it take to execute if num has the value of 150? Useboth the exact computation and the approximate computation and compare how closethey are by computing their percentage difference.

14. The C++ language report defines the for statement in terms of an equivalent whilestatement. (a) Using the definition, predict the output of the following code fragment.

int last = 10;for (int i = 0; i <= last; i+=2) {

cout << "i = " << i << endl;cout << “last = “ << last++ << endl;

}

(b) Execute the code fragment. Was your prediction correct?

15. Write the algorithm of Figure 9.8 to find the average value in GCL.

16. Write the algorithm of Figure 9.15 to find the sum of consecutive integers in GCL.

Problems

17. Write a Qt program that outputs to a QLabel the average of a list of values that are dis-played in a QTextEdit, or a statement that there are no values in the window.

18. Write a Qt program that outputs to a QLabel the maximum integer value from a list ofintegers in a QTextEdit. Output an appropriate message if no integer values are in theQTextEdit.

19. Modify the program in Figure 9.13 so that it also outputs the number of times thewhile loop executes. Run the modified program five times with the following toler-ances: 1e–2, 1e–3, 1e–4, 1e–5, 1e–6. Graph the number of times the loop executes (y-axis) versus the tolerance (x-axis). What mathematical relationship did you discoverbetween these two quantities? Hint: Use semilog graph paper or, equivalently, let eachx-axis division be 10 times greater than the previous x-axis division. For what values ofthe tolerance, if any, will the loop never execute?

20. Modify the program in Figure 9.13 to always print the solution to four places past the

Page 26: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

56 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

decimal point and to print an error message if the user enters a negative number or zerofor the tolerance.

21. Write a program to compute and output to a QLabel the sum of all positive even inte-gers less than or equal to a value entered by the user in a QSpinBox.

22. Write a program to compute and output to a QLabel the sum of all positive odd integersless than or equal to a value entered by the user in a QSpinBox.

23. A text file that you create contains a list of integers. Write a program that counts howmany even integers there are in the text file. For example, if the file contains

5 38 1 -45 21 -7 12 5

the program should display a QLabel that says “There are 2 even integers in the file”.You can test if an integer n is even with (n % 2 == 0).

24. A QTextEdit contains a list of integers. Write a program that counts how many positiveintegers are in the window. For example, if the QTextEdit contains

5 38 1 -45 21 -7 12 5

the program should display a QLabel that says “There are 6 positive integers in thewindow”.

25. A linear sequence is a list of integers, each of which is a constant integer increment ofthe previous integer. For example,

3 6 9 12 15 18

is a linear sequence because each number is three plus the previous one. The constantincrement need not be three, however. Write a program that inputs a list of numbersfrom a text edit and displays on a label whether the sequence is linear, and the constantincrement if it is. For example, the QLabel for the above list should state, “Thesequence is linear with an increment of 3.” The QLabel for the sequence,

3 6 9 12 16 19

should state, “The sequence is not linear.” Consider the empty list and any list withonly one integer to be not linear.

26. A geometric sequence is a list of integers, each of which is a constant integer multipleof the previous integer. For example,

3 6 12 24 48 96

is a geometric sequence because each number is two times the previous one. The con-stant multiple need not be two, however. Write a program that inputs a list of numbersfrom a QTextEdit and displays on a QLabel whether the sequence is geometric, and theinteger multiple if it is. For example, the dialog box for the above list should state,“The sequence is geometric with a multiple of 2.” The message for the sequence,

3 6 12 24 46 92

Page 27: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Problems 57

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

should state, “The sequence is not geometric.” Consider the empty list and any list withonly one integer to be not geometric.

27. A salesperson gets a 5% commission on sales of $1000 or less, and a 10% commissionon sales in excess of $1000. For example, a sale of $1300 earns him $80—that is $50on the first $1000 of the sale and $30 on the $300 in excess of the first $1000. A textfile contains a salesperson’s ID number (string) and his sales amount (real) on eachline. Write a program that outputs to a QTextBrowser a report containing the ID num-ber, the amount of sales, and the commission for each salesperson. At the bottom of thereport, print the ID number of the salesperson who sold the most. For example, if thetext file contains

EM-00134 580.00EM-01209 600.00EM-00030 1000.00EM-02238 1200.00EM-09411 800.00EM-02344 1150.00

the report on the QTextBrowser should be

EM-00134 580.00 29.00EM-01209 600.00 30.00EM-00030 1000.00 50.00EM-02238 1200.00 70.00EM-09411 800.00 40.00EM-02344 1150.00 65.00Highest sales ID: EM-02238

Page 28: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

58 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

28. The price per Frisbee depends on the quantity ordered, as indicated in Figure 9.19. Atext file contains a list of numbers that represent order quantities of Frisbees. Write aprogram that outputs to a QTextBrowser a report of order quantities and the cost perorder. At the bottom of the report print the total cost of all the orders. For example, ifthe input file contains

50 150 20 200 300 1 250 100

the report in the QTextBrowser should be

50 250.00150 450.0020 100.00

200 500.00300 600.00

1 5.00250 625.00100 300.00

Total: 2830.00

29. An instructor determines the total score for each student according to the weights ofFigure 9.20. A total of 90 to 100 is a grade of A, 80 to 89 is a B, and so on for C, D, andF. Each line of a text file contains four real values that are the homework, exam, andfinal exam scores in that order. Write a program that outputs to a QTextBrowser a table,each line of which contains

" The four values of each score" The weighted total" The letter grade

At the bottom of the report print the average of the weighted totals.

30. The number of runs for each team in each inning of a Dodgers versus Giants baseballgame is in a text file. The Dodgers bat first. A complete game lasts nine innings. Afterthe last Dodger out in the top of the ninth inning, if the Giants are ahead they do not batin the bottom of the ninth. The game is over and the Giants win. In that case, no valueis in the text file for the number of Giants runs in the bottom of the ninth, not even azero.

If it is a tie game or if the Dodgers are ahead after their last out, the Giants bat in the

Quantity Price per Frisbee

0 – 99 $ 5.00

100 – 199 3.00

200 – 299 2.50

300 or more 2.00

Figure 9.19The price schedule for Problem 28.

Page 29: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Problems 59

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

bottom of the ninth. After the last Giant out, whoever is ahead wins. If it is a tie, thegame goes into extra innings, after which the same termination conditions apply as inthe ninth inning.

Write a program that continues to input the runs for each inning until one team wins.Announce the winner, the score, and the number of innings played. Assume there areno input errors in the text file. The program must not attempt to read past the end oftext. Do not use the stream.atEnd() function.

The loop termination condition for this problem cannot be conveniently written as asingle expression. Declare a boolean variable named over that indicates when thegame is over. Initialize it to false before entering your WHILE loop, which should exe-cute once for each inning. The test for termination should be on !over. The processingat the bottom of the loop body should be a computation for determining if the game isover.

31. If a volleyball team serves the ball and wins the volley, they get 1 point and they get toserve again. If they serve the ball and lose the volley, the opposing team does not get apoint. But the opposing team does win the right to serve next. The first team to get 15points wins the game, except that they must win by at least 2 points. If the score is 15to 14, play continues until one team is ahead by 2.

A text file contains a sequence of 1’s and 0’s for a volleyball team that serves first in agame. A 1 represents winning the volley and a 0 represents losing the volley. For exam-ple, the sequence at the beginning of the file

1 1 0 1 0 0

represents

" Winning a volley and a point" Winning a volley and a point" Losing the serve" Winning the serve back" Losing the serve" Losing the volley and a point

after which the team is ahead, 2 to 1.

Score item Percent toward total

Homework 15

Exam 1 25

Exam 2 25

Final exam 35

Figure 9.20The grading weights for Problem 29.

Page 30: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

60 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

Write a program that continues to scan the 1’s and 0’s until the game is over. Output thescore and state whether the team won or lost. Assume there are no input errors in thetext file. The program must not attempt to read past the end of text. Do not use theQTextStream atEnd function.

The loop termination condition for this problem cannot be conveniently written as asingle expression. Declare a boolean variable named over that indicates when thegame is over. Initialize it to false before entering your while loop, which should exe-cute once for each input value. The test for termination should be on !over. The pro-cessing at the bottom of the loop body should be a computation for determining if thegame is over.

32. A businessman wants to claim depreciation of an asset with the straight line method. Ifthe asset has a useful life of n years, then of its original value is subtracted eachyear. Write a program that asks for the asset’s value and its useful life span in a QDou-bleSpinBox and QSpinBox, respectively, and outputs a depreciation schedule to aQTextBrowser using the straight line method. For example, if the user enters 1000.00for the value of the asset and 5 years for the lifesaving the report in the QTextBrowsershould be

0 1000.001 800.002 600.003 400.004 200.005 0.00

33. A businessman wants to claim depreciation of an asset with the double declining bal-ance method. If the asset has a useful life of n years, then times its current valueis subtracted each year. Write a program that asks for the asset’s value and its usefullife-span in a QDoubleSpinBox and QSpinBox, respectively, and outputs a deprecia-tion schedule to a QTextBrowser using the double declining balance method. Forexample, if the user enters 1000.00 for the value of the asset and 5 years for the lifesav-ing the report in the QTextBrowser should be

0 1000.001 600.002 360.003 216.004 129.605 77.76

34. The factorial of an integer n is

For example, the factorial of 4 is 24, because . Zero factorial isdefined to be one. Write a program that asks the user to input a nonnegative integer in aQSpinBox, then computes and outputs the factorial of that number in a QLabel. If thenumber entered is negative, compute nothing and do not change any fields in the dialogbox.

1 n

2 n

n! n n 1–( ) n 2–( ) … 3 2 1# # # # # #=

4 3 2 1# # # 24=

Page 31: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Problems 61

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

35. Suppose that x is a real nonzero number and n is an integer. Then x raised to the nthpower, written mathematically as , means

where there are n x’s in the first and last expressions. Without using the cmath library,write a program that inputs a double and an int in a QDoubleSpinBox and QSpinBox,respectively, and raises the double to the power indicated by the int. For example, if theuser enters 2.0 for the double and -3 for the power, a QLabel should display 0.125.

36. The base of the natural logarithms, e, is approximated with four terms as

Notice that the fourth term is 1/3 times the previous term. In general, the nth term is 1/(n – 1) times the previous term. Write a program that asks the user to input the numberof terms in a QSpinBox and outputs the approximation of e in a QLabel. Use two vari-ables in additional to your control variable—sum, which represents the sum computedso far, and term, which represents the value of the current term. Initialize sum to thefirst term outside the loop, and start the loop with the second term. For example, if theuser enters 4 for the number of terms, the value 2.6666… should be output. If the num-ber entered is negative or zero, compute nothing and do not change any fields in thedialog box.

37. The average or mean of n numbers, , is

The standard deviation, a measure of how scattered the n numbers are, is defined as

when the numbers are a random sample of a population. If the numbers are all close toeach other, they will all be close to the mean, their differences from the mean will besmall, and the standard deviation will be small.

(a) An input file contains a sequence of doubles. Write a program that computes andoutputs to a QLabel the standard deviation of the doubles from the definition. Displaythe result with four places past the decimal point, and write an error message if there isonly one value or no values in the text file. You will need one loop to compute the

xn

x x … x# # # if n 0>1.0 if n 0=

1.0 x x … x# # #( ) if n 0<

11--- 1

1 1( )----------- 1

1 1( ) 2( )------------------- 1

1 1( ) 2( ) 3( )---------------------------+ + +

x1 x2 … xn, , ,

xx1 x2 … xn+ + +

n----------------------------------------=

1n--- xii 1=

n

$=

s

xi x–( )2

i 1=

n

$n 1–

------------------------------=

Page 32: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

62 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006

mean, followed by a second execution of the QTextStream constructor to position theQTextStream at the beginning of the text string again, followed by another loop for thesquares of the differences from the mean.

(b) A mathematically equivalent formula for the standard deviation is

(Can you derive this formula from the definitions of the mean and standard deviation?)This formula only requires one loop, because you can accumulate the sum of thesquares at the same time you are accumulating the sum for the mean. Write a programthat computes and outputs to a QLabel the standard deviation from this formula usingonly one loop. Display the result with four places past the decimal point, and write anerror message if there is only one value or no values in the text file.

38. An integer greater than 1 is prime if the only positive integers that divide it are 1 andthe number itself. For example, 13 is prime because it is divisible only by 1 and 13,while 15 is not prime because it is divisible by 1, 3, 5, and 15. Write a Qt program thatasks the user to input a positive integer in a QSpinBox and then outputs a message to aQLabel indicating whether the integer is prime.

39. Write a program that asks the user to enter a positive integer in a QSpinBox, then out-puts to a QLabel all the positive factors of that number. If the number entered is lessthan 1, compute nothing and output an appropriate message to the QLabel. For exam-ple, if the input is 15 then the output should be

1 3 5 15

40. The first two Fibonacci numbers are 0 and 1. The third Fibonacci number is the sum ofthe first pair, 0 plus 1, which is 1. The fifth is the sum of the previous pair, 1 plus 2,which is 3. The first seven Fibonacci numbers are

0 1 1 2 3 5 8

each number being the sum of the two previous numbers. Write a program that asks theuser to enter an integer in a QSpinBox, and outputs to a QLabel that many Fibonaccinumbers. If the number entered is less than 2, compute nothing and output an appropri-ate message to the QLabel. For example, if the user enters 7 the program should outputthe seven numbers listed above.

41. Implement a dialog box that looks and behaves like Figure 7.XXX, but with one addi-tional button labeled “A Gets B”. When the user presses this button Stack A should becleared and then given a copy of Stack B. The text fields for Push and Pop should notchange. Only the field for the number of items in stack A should change. Use a tempo-rary stack variable called tempStack in your procedure AGetsB to first store the valueof Stack B in reverse order by popping all the items from Stack B into it. Then, clearStack A and copy all the items from tempStack into it and back into Stack B.

s

xi2

i 1=

n

$ nx2

n 1–-------------------------------=

Page 33: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

Problems 63

Revised: October 30, 2006 Copyright © 2005, Bradley E. Cupp and J. Stanley Warford

42. Implement a dialog box that looks and behaves like Figure 7.XXX, but with one addi-tional button labeled “A Gets B”. When the user presses this button List A should becleared and then given a copy of List B. All the text fields for the dialog box should notchange. Only the field for the number of items in List A should change. Import modulePboxListADT. Use a temporary variable called temp of type PboxListADT.T in yourprocedure AGetsB to store the value between the retrieve and insert operations.

43. Implement a dialog box that looks and behaves like Figure 7.XXX, but with one addi-tional button labeled “Top To Bottom”. If the stack contains two or more items whenthe user presses this button, the top item on the stack should be moved to the bottom ofthe stack. Otherwise, the stack should remain unchanged. The text fields for Push andPop should not change, nor should the field for the number of items change. Use a tem-porary variable called temp to store the top value of the stack and another temporaryvariable called tempStack to store the remainder of the stack in your procedure Top-ToBottom. Import module PboxStackADS.

44. Implement a dialog box that looks and behaves like Figure 7.XXX, but with one addi-tional button labeled “A Append B”. If the length of List A plus the length of List B isgreater than the capacity of a list when the user presses this button, nothing should hap-pen. Otherwise, a copy of List B should be appended to the end of List A. All the textfields for the dialog box should not change. Only the field for the number of items inList A should change. Import module PboxListADT. Use a temporary variable calledtemp of type PboxListADT.T in your procedure AAppendB to store the value betweenthe retrieve and insert operations.

45. Implement a dialog box that looks and behaves like Figure 7.XXX, but with one addi-tional button labeled “Reverse”. When the user presses this button, all the items of thelist should be rearranged in reverse order. All the text fields for the dialog box shouldnot change. Import module PboxListADS. Use two local variables, i initialized to 0and j initialized to Length() - 1. While i is less than j, switch the items at positionsi and j followed by INC(i) and DEC(j). Use a temporary variable called temp oftype PboxListADS.T in your procedure ReverseA to store the value between theretrieve, remove, and insert operations

Page 34: CFQ t 9 - Pepperdine University · CFQ t 9 - Pepperdine University ... s $ = -----

64 Chapter 9 Loops

Copyright © 2005, Bradley E. Cupp and J. Stanley Warford Revised: October 30, 2006