u+1=v действительно является постусловием цикла while (как вы думаете, почему это «явно» не так?). Это всегда имеет место в цикле while, который не содержит break
: при выходе из цикла это может быть только потому, что условие цикла (здесь ) является ложным. Это не единственное, что будет верно, когда цикл выйдет отсюда (этот алгоритм фактически вычисляет что-то интересное, как вы видели в своем классе, так что и также являются постусловиями), но это наиболее очевидно.u+1≠vu=[this interesting thing]v=[this interesting thing]
Теперь, чтобы найти другие интересные свойства, нет общего рецепта. На самом деле, существует некоторый формальный смысл, в котором нет общего рецепта для поиска инвариантов цикла. Лучшее, что вы можете сделать, - это применить некоторые методы, которые работают только в некоторых случаях, или вообще ловить рыбу для интересных наблюдений (которые работают все лучше и лучше, когда вы становитесь более опытными).
Если вы запустите цикл для нескольких итераций с некоторым значением , вы увидите это на каждой итерации:n
- либо подпрыгиваете до ;u(u+v)/2
- или понижается до .v(u+v)/2
В частности, начинаете меньше, чем , и никогда не обгоните его. Кроме того, начинается с положительного значения и увеличивается, а начинается с и уменьшается. Таким образом, является инвариантом всей этой программы.uvuvn+10≤u≤v≤n+1
Одна вещь, которая не так очевидна, - может ли когда-либо быть равен . Это важно: если и когда-нибудь станут равными, у нас будет и цикл будет продолжаться вечно. Таким образом, вам нужно доказать, что и никогда не становятся равными, чтобы доказать, что алгоритм корректен (то есть не зацикливается вечно). Как только эта потребность была определена, легко доказать (я оставляю это как упражнение), что является инвариантом цикла (имейте в виду, что и являются целыми числами, так что это эквивалентно ).uvuvx=u=vuvu<vuvu+1≤v
Поскольку в конце программы, заданное вами постусловие также можно записать как (часть тривиальна). Причина, по которой нам нужно подобное пост-условие с участием , заключается в том, что мы хотим связать результат программы с входом . Почему это точное условие? Мы ищем что-то максимально точное и смотрим, где появляется внутри цикла:v=u+1u2≤n<v20≤u2nnn
- у нас есть ;u≤x≤v
- когда , мы выбираем следующий равным , так что (и не изменяется);x2≤nuxu2≤nv
- когда , мы выбираем следующий равным , так что (и не меняется).x2>nvxn<v2u
Эта дихотомия намекает на то, что, возможно, все время. Другими словами, мы подозреваем, что это инвариант цикла. Проверка этого оставлена читателю как упражнение (не забудьте проверить, что свойство изначально истинно).u2≤n<v2
И теперь, когда мы сделали все это, мы видим, что и : - квадратный корень из округленный до ближайшего целого числа.( u + 1 ) 2 > n u nu2≤n(u+1)2>nun