I had intended to talk about preconditions, postconditions, and loop invariants in the discussion meeting but abandoned the example I was doing in order to give you more time to work on the other questions. So you didn't have much background for the last two questions, and hardly any of you got to them in any case. Have a look at Excursion 1.3 in the textbook to see what I was talking about.
Since x is even, it is equal to 2y for some natural y. Its successor is then
equal to 2y+1, which is twice a natural plus 1 and thus is odd.
Now assume x is odd, so that x = 2y + 1 for some natural y. The successor
of x is 2y + 2 = 2(y + 1), which is even because it is twice a natural.
First assume that x is even and positive. Since it is even, it equals 2y for
some y. If y were 0, then 0 would be 0, which it isn't, so we can assume that
y has a predecessor y - 1. By arithmetic, x's predecessor x - 1 i equal to
2y - 1 = 2(y-1) + 1. So this predecessor is twice a natural plus one and is
thus odd.
Now assume that x is odd, so that x = 2y + 1 for some y. The predecessor
of x is 2y, which is twice a natural and thus is even.
Assume that there is some natural that is neither odd nor even, and let x be the least such natural. This x cannot be 0, because 0 = 2(0) is even. So x has a predecessor x-1, and this number must be either odd or even because x is the least number that is neither and x-1 is less than x. But by (1), if x-1 is even then x is odd and if x-1 is odd then x is even. So either way, x is either even or odd, and we have a contradiction. Since the assumption that there was a neither-odd-nor-even natural led to a contradiction, no such natural exists.
public boolean isEven (natural x)
{// returns whether x is an even number
natural i = 0;
while (true) {
if (x == 2 * i) return true;
if (x == 2 * i + 1) return false;
i++;}}
For partial correctness we must prove that if the method terminates,
it gives the correct answer. The only way it can terminate is through
one of the return statements. If we return "true", we have just seen that
x is 2 times a natural, so x is even. If we
return "true", we have just seen that x is 2 times some natural plus 1, so we
know that x is odd, and then by (4) we know it is not even.
For termination on any given x, we need to know that the loop will find
the correct i such that x = 2i or x = 2i + 1 is true. (Since x is either even
or odd by (3), such an i must exist.) Assume that there is a number for which
the method does not terminate, and let z be the least such number. Let k be the
natural such that z = 2k or z = 2k+1. This z
cannot be 0 or 1, because clearly the code terminates on 0 or 1 with i = 0.
So the natural z - 2 exists, and the method terminates on input z - 2. Since
z - 2 is smaller than z, the method terminates on input z - 2. Since z - 2 is
equal to either 2(k - 1) or 2(k - 1) + 1, the method must eventually set i to
be k - 1. But then, on the next time through the loop, it sets i to k and
then one of the if
statements will cause the method to return.
public boolean isEven (natural x)
{// returns whether x is an even number
if (x == 0) return true;
if (x == 1) return false;
return !isEven (x - 1);}
To prove partial correctness, assume that there exists a natural on which the
method terminates with the wrong answer. Let z be the smallest such natural.
This z cannot be 0 (or 1), because we can see that the method gives the right
answer on those inputs. So z - 1 must exist, and since z - 1 is smaller than
z, if the method terminates on input z - 1 it must give the right answer. But
if the method terminates on z, it must do so by calling itself on z - 1 and
giving the opposite answer. And by (2), we know that z - 1 is odd if z is even
and vice versa, so that To prove termination, assume that there is a natural on which the method
does not terminate and let z be the least such number. This z cannot be 0 or
1 because the method clearly terminates on both of those inputs. So the natural
z - 1 exists, and because z - 1 is smaller than z, we know that the method
terminates on input z - 1. But then it also terminates on input z, because
then it calls itself on input z - 1. This contradicts our assumption.
!isEven (z - 1)
correctly tells whether z
is even. So the answer on z is correct, contradicting the assumption.
Last modified 13 September 2007