0% found this document useful (0 votes)
24 views

Ref Part 2

Uploaded by

pour htc820
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views

Ref Part 2

Uploaded by

pour htc820
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

22 INTRODUCTION TO COMPUTATION AND PROGRAMMING USING PYTHON

2.4 Iteration
We closed Section 2.2 with the observation that most computational tasks cannot
be accomplished using branching programs. Consider, for example, writing a
program that asks the user how many time he wants to print the letter X, and
then prints a string with that number of X’s. We might think about writing
something like
numXs = int(input('How many times should I print the letter X? '))
toPrint = ''
if numXs == 1:
toPrint = 'X'
elif numXs == 2:
toPrint = 'XX'
elif numXs == 3:
toPrint = 'XXX'
#...
print(toPrint)

But it would quickly become apparent that we would need as many conditionals
as there are positive integers—and there are an infinite number of those. What
we need is a program that looks like
numXs = int(input('How many times should I print the letter X? '))
toPrint = ''
concatenate X to toPrint numXs times
print(toPrint)

When we want a program to do the same thing many times, we can use itera-
tion. A generic iteration (also called looping) mechanism is shown in the boxed-
in part of Figure 2.4. Like a conditional statement, it begins with a test. If the test
evaluates to True, the program executes the loop body once, and then goes back
to reevaluate the test. This process is repeated until the test evaluates to False, af-
ter which control passes to the code following the iteration statement.
We can write the kind of loop depicted in Figure 2.4 using a while statement.
Consider the following example:
# Square an integer, the hard way
x = 3
ans = 0
itersLeft = x
while (itersLeft != 0):
ans = ans + x
itersLeft = itersLeft - 1
print(str(x) + '*' + str(x) + ' = ' + str(ans))
CHAPTER 2. INTRODUCTION TO PYTHON 23

Figure 2.4 Flow chart for iteration

The code starts by binding the variable x to the integer 3. It then proceeds to
square x by using repetitive addition. The table in Figure 2.5 shows the value as-
sociated with each variable each time the test at the start of the loop is reached.
We constructed it by hand-simulating the code, i.e., we pretended to be a Python
interpreter and executed the program using pencil and paper. Using pencil and
paper might seem kind of quaint, but it is an excellent way to understand how a
program behaves.16
Test # x ans itersLeft
1 3 0 3
2 3 3 2
3 3 6 1
4 3 9 0

Figure 2.5 Hand simulation of a small program

The fourth time the test is reached, it evaluates to False and flow of control
proceeds to the print statement following the loop. For what values of x will this
program terminate? There are three cases to consider: x == 0, x > 0, and x < 0.
Suppose x == 0. The initial value of itersLeft will also be 0, and the loop
body will never be executed.
Suppose x > 0. The initial value of itersLeft will be greater than 0, and the
loop body will be executed at least once. Each time the loop body is executed, the
value of itersLeft is decreased by exactly 1. This means that if itersLeft started
out greater than 0, after some finite number of iterations of the loop, itersLeft

16 It is also possible to hand-simulate a program using pen and paper, or even a text editor.
24 INTRODUCTION TO COMPUTATION AND PROGRAMMING USING PYTHON

will equal 0. At this point the loop test evaluates to False, and control proceeds to
the code following the while statement.
Suppose x < 0. Something very bad happens. Control will enter the loop, and
each iteration will move itersLeft farther from 0 rather than closer to it. The
program will therefore continue executing the loop forever (or until something
else bad, e.g., an overflow error, occurs). How might we remove this flaw in the
program? Initializing itersLeft to the absolute value of x almost works. The loop
terminates, but it prints a negative value. If the assignment statement inside the
loop is also changed, to ans = ans + abs(x), the code works properly.

Finger exercise: Replace the comment in the following code with a while loop.
numXs = int(input('How many times should I print the letter X? '))
toPrint = ''
#concatenate X to toPrint numXs times
print(toPrint)

It is sometimes convenient to exit a loop without testing the loop condition.


Executing a break statement terminates the loop in which it is contained, and
transfers control to the code immediately following the loop. For example, the
code
#Find a positive integer that is divisible by both 11 and 12
x = 1
while True:
if x%11 == 0 and x%12 == 0:
break
x = x + 1
print(x, 'is divisible by 11 and 12')

prints
132 is divisible by 11 and 12

If a break statement is executed inside a nested loop (a loop inside another


loop), the break will terminate the inner loop.
We have now covered pretty much everything about Python that we need to
know to start writing interesting programs that deal with numbers and strings. In
the next chapter, we take a short break from learning Python, and use what we
have already learned to solve some simple problems.

Finger exercise: Write a program that asks the user to input 10 integers, and then
prints the largest odd number that was entered. If no odd number was entered, it
should print a message to that effect.
3 SOME SIMPLE NUMERICAL PROGRAMS

Now that we have covered some basic Python constructs, it is time to start think-
ing about how we can combine those constructs to write some simple programs.
Along the way, we’ll sneak in a few more language constructs and some algo-
rithmic techniques.

3.1 Exhaustive Enumeration


The code in Figure 3.1 prints the integer cube root, if it exists, of an integer. If the
input is not a perfect cube, it prints a message to that effect.

#Find the cube root of a perfect cube


x = int(input('Enter an integer: '))
ans = 0
while ans**3 < abs(x):
ans = ans + 1
if ans**3 != abs(x):
print(x, 'is not a perfect cube')
else:
if x < 0:
ans = -ans
print('Cube root of', x,'is', ans)

Figure 3.1 Using exhaustive enumeration to find the cube root

For what values of x will this program terminate? The answer is, “all inte-
gers.” This can be argued quite simply.
• The value of the expression ans**3 starts at 0, and gets larger each time
through the loop.
• When it reaches or exceeds abs(x), the loop terminates.
• Since abs(x) is always positive there are only a finite number of iterations be-
fore the loop must terminate.
Whenever you write a loop, you should think about an appropriate decre-
menting function. This is a function that has the following properties:
26 INTRODUCTION TO COMPUTATION AND PROGRAMMING USING PYTHON

• It maps a set of program variables into an integer.


• When the loop is entered, its value is nonnegative.
• When its value is ≤ 0, the loop terminates.
• Its value is decreased every time through the loop.
What is the decrementing function for the while loop in Figure 3.1? It is
abs(x) - ans**3.

Now, let’s insert some errors and see what happens. First, try commenting
out the statement ans = 0. The Python interpreter prints the error message
NameError: name 'ans' is not defined
because the interpreter attempts to find the value to which ans is bound before it
has been bound to anything. Now, restore the initialization of ans, replace the
statement ans = ans + 1 by ans = ans, and try finding the cube root of 8. After
you get tired of waiting, enter “control c” (hold down the control key and the c
key simultaneously). This will return you to the user prompt in the shell.
Now, add the statement
print('Value of the decrementing function abs(x) - ans**3 is',
abs(x) - ans**3)

at the start of the loop, and try running it again. This time it will print
Value of the decrementing function abs(x) - ans**3 is 8

over and over again.


The program would have run forever because the loop body is no longer re-
ducing the distance between ans**3 and abs(x). When confronted with a pro-
gram that seems not to be terminating, experienced programmers often insert
print statements, such as the one here, to test whether the decrementing function
is indeed being decremented.
The algorithmic technique used in this program is a variant of guess and
check called exhaustive enumeration. We enumerate all possibilities until we get
to the right answer or exhaust the space of possibilities. At first blush, this may
seem like an incredibly stupid way to solve a problem. Surprisingly, however, ex-
haustive enumeration algorithms are often the most practical way to solve a
problem. They are typically easy to implement and easy to understand. And, in
many cases, they run fast enough for all practical purposes. Make sure to remove
or comment out the print statement that you inserted and to reinsert the state-
ment ans = ans + 1, and then try finding the cube root of 1957816251. The pro-
gram will finish almost instantaneously. Now, try 7406961012236344616.
CHAPTER 3. SOME SIMPLE NUMERICAL PROGRAMS 27

As you can see, even if millions of guesses are required, it’s not usually a
problem. Modern computers are amazingly fast. It takes on the order of one na-
nosecond—one billionth of a second—to execute an instruction. It’s a bit hard to
appreciate how fast that is. For perspective, it takes slightly more than a nanosec-
ond for light to travel a single foot (0.3 meters). Another way to think about this
is that in the time it takes for the sound of your voice to travel a hundred feet, a
modern computer can execute millions of instructions.
Just for fun, try executing the code
maxVal = int(input('Enter a postive integer: '))
i = 0
while i < maxVal:
i = i + 1
print(i)

See how large an integer you need to enter before there is a perceptible pause be-
fore the result is printed.

Finger exercise: Write a program that asks the user to enter an integer and prints
two integers, root and pwr, such that 0 < pwr < 6 and root**pwr is equal to the in-
teger entered by the user. If no such pair of integers exists, it should print a mes-
sage to that effect.

3.2 For Loops


The while loops we have used so far are highly stylized. Each iterates over a se-
quence of integers. Python provides a language mechanism, the for loop, that can
be used to simplify programs containing this kind of iteration.
The general form of a for statement is (recall that the words in italics are de-
scriptions of what can appear, not actual code):
for variable in sequence:
code block
The variable following for is bound to the first value in the sequence, and the
code block is executed. The variable is then assigned the second value in the se-
quence, and the code block is executed again. The process continues until the se-
quence is exhausted or a break statement is executed within the code block.
The sequence of values bound to variable is most commonly generated using
the built-in function range, which returns a series of integers. The range function
takes three integer arguments: start, stop, and step. It produces the progression
start, start + step, start + 2*step, etc. If step is positive, the last element is the
28 INTRODUCTION TO COMPUTATION AND PROGRAMMING USING PYTHON

largest integer start + i*step less than stop. If step is negative, the last element is
the smallest integer start + i*step greater than stop. For example, the expression
range(5, 40, 10) yields the sequence 5, 15, 25, 35, and range(40, 5, -10) yields
the sequence 40, 30, 20, 10. If the first argument is omitted it defaults to 0, and
if the last argument (the step size) is omitted it defaults to 1. For example,
range(0, 3) and range(3) both produce the sequence 0, 1, 2. The numbers in the
progression are generated on an “as needed” basis, so even expressions such as
range(1000000) consume little memory.17 We will discuss range in more depth in
Section 5.2.
Less commonly, we specify the sequence to be iterated over in a for loop by
using a literal, e.g., [0, 3, 2].
Consider the code
x = 4
for i in range(0, x):
print(i)

It prints
0
1
2
3

Now, think about the code


x = 4
for i in range(0, x):
print(i)
x = 5

It raises the question of whether changing the value of x inside the loop affects
the number of iterations. It does not. The arguments to the range function in the
line with for are evaluated just before the first iteration of the loop, and not
reevaluated for subsequent iterations.
To see how this works, consider
x = 4
for j in range(x):
for i in range(x):
print(i)
x = 2

17In Python 2, range generates the entire sequence when invoked. Therefore, expressions such as
range(1000000) use quite a lot of memory. In Python 2, xrange behaves the way range behaves in
Python 3.
CHAPTER 3. SOME SIMPLE NUMERICAL PROGRAMS 29

which prints
0
1
2
3
0
1
0
1
0
1

because the range function in the outer loop is evaluated only once, but the range
function in the inner loop is evaluated each time the inner for statement is
reached.
The code in Figure 3.2 reimplements the exhaustive enumeration algorithm
for finding cube roots. The break statement in the for loop causes the loop to
terminate before it has been run on each element in the sequence over which it is
iterating.

#Find the cube root of a perfect cube


x = int(input('Enter an integer: '))
for ans in range(0, abs(x)+1):
if ans**3 >= abs(x):
break
if ans**3 != abs(x):
print(x, 'is not a perfect cube')
else:
if x < 0:
ans = -ans
print('Cube root of', x,'is', ans)

Figure 3.2 Using for and break statements

The for statement can be used in conjunction with the in operator to conven-
iently iterate over characters of a string. For example,
total = 0
for c in '12345678':
total = total + int(c)
print(total)

sums the digits in the string denoted by the literal '12345678' and prints the total.

You might also like