Under exact integer arithmetic, the intended result is , using the ceiling function. A sufficient loop invariant isInitially , and the final disjunction is true. If the guard holds, the old value is below . Incrementing
i and doubling y therefore preserves and makes the new lower bound true. At exit . If , positivity of forces ; otherwise . Both cases establish the claimed postcondition. Doubling eventually reaches or exceeds any fixed positive , proving algorithm termination in this arithmetic model. This is the doubling-loop ceiling logarithm argument.The printed Scala implementation is not correct for its entire stated
Int domain. Its y is an Int. For , it reaches , wraps to on the next doubling, then becomes zero and stays zero. The guard remains true forever. The loop invariant above is valid for the printed code only when . Scala documents Int as a signed 32-bit value equivalent to Java's primitive int.[ref]A corrected implementation for every positive
Int input widens the doubling variable before any multiplication:def ceilingLog2(x: Int): Int = {
require(x > 0)
var i = 0
var y = 1L
while (y < x.toLong) {
i += 1
y *= 2L
}
i
}Now at most 31 iterations are needed and , safely within
Long. The same loop invariant proves total correctness without the overflow gap. Articles by others on the same topic
There are currently no matching articles.