|
|
||
A DigressionFor those new to programming, here's a short digression, adapted from chapter 8 of Edsger Dijkstra's book, A Discipline of Programming [Dijkstra76]. Let's say we need to set a variable, Clearly, we need to choose correctly between two different assignment statements. We need to do either m=a or m=b . How do we make this choice? With a little logic, we can derive the condition by taking each of these statement's effects out of the desired end-state. For the statement
m=a
to be the right statement
to use, we show the effect of the statement by replacing
For the statement
m=b
to be the right statement
to establish the necessary condition, we do a similar replacement of
Each assignment statement can be "guarded" by an appropriate condition. if a>=b: m=a elif b>=a: m=b Is the correct statement to set Note that the hard part is establishing the post condition. Once we have that stated correctly, it's relatively easy to figure the basic kind of statement that might make some or all of the post condition true. Then we do a little algebra to fill in any guards or loop conditions to make sure that only the correct statement is executed. Successful Loop Design. There are several considerations when using the while statement. This list is taken from David Gries', The Science of Programming [Gries81].
While these conditions seem overly complex for something so simple as a loop, many programming problems arise from missing one of them. Gries recommends putting comments around a loop showing the conditions before and after the loop. Since Python provides the assert statement; this formalizes these comments into actual tests to be sure the program is correct.
Designing a Loop. Let's put a particular loop under the microscope. This is a small
example, but shows all of the steps to loop construction. We want to
find the least power of 2 greater than or equal to some number greater
than 1, call it We can state this mathematically as looking for some number,
We can start to sketch our loop already. assert x > 1 ... initialize ... ... some loop ... assert 2**(n-1) < x <= 2**n We work out the initialization to make sure that the invariant
condition of the loop is initially true. Since assert x > 1
n= 1
... some loop ...
assert 2**(n-1) < x <= 2**n
In loops, there must be a condition on the body that is invariant,
and a terminating condition that changes. The terminating condition is
written in the
while
clause. In this case, it is
invariant (always true) that 2**( assert x > 1 n= 1 while not ( x <= 2**n ): n= n + 1 assert 2**(n-1) < x assert 2**(n-1) < x <= 2**n The next to last step is to show that when the
while
condition is true, there are more than zero trips
through the loop possible. We know that The final step is to show that each cycle through the loop reduces
the trip count. We can argue that increasing We should add this information on successful termination as comments in our loop. |
||