Tucker and Noonan's presentation of the Fibonacci example in Section 3.4.3 has lots of glitches. Since I don't particularly care for this example, I'd rather work a different one than fix theirs up.
Specifically, let's consider a procedure for multiplying two
integers, the first of which we will assume is not negative. Of
course, the simplest way to do this would be using *
, but
let's do it with one arm tied behind our back. (The resulting
algorithmic ideas apply more realistically in other settings.) A
straightforward Java version of this
procedure is attached. The first thing we might do would be to
add in some assertions for the procedure's precondition,
postcondition, and loop invariant. The version with those few assertions is also
attached. Finally, if we wanted to really show off our understanding
of axiomatic semantics, we could create a version
with a lot more assertions added to nail down all the details of
the correctness proof.
It is worth remembering that we are actually only proving partial correctness. To make that point, we can consider a variant, also available with no assertions, a few assertions, or the whole nine yards. This variant has the virtue not only that it has a simpler loop invariant, but also that it doesn't require the precondition that the first argument be greater than or equal to zero. However, think carefully about what we prove: this procedure, unlike the first one, won't return a wrong answer when given a negative first argument. But that doesn't mean it will return the right answer!
For a more complicated example, which will also bring in the proof rule for conditionals, we can consider making the procedure more efficient by cutting the multiplier in half (when possible) rather than just subtracting one. This more advanced version is also available with no assertions, a few assertions, or every conceivable assertion.