es de hecho una condición posterior del ciclo while (¿por qué crees que no es "claramente" el caso?). Este es siempre el caso con un ciclo while que no contiene un: cuando el ciclo sale, solo puede ser porque la condición del ciclo (aquí, u + 1 ≠ v ) es falsa. No es lo único que será cierto cuando el ciclo salga aquí (este algoritmo realmente calcula algo interesante, como viste en tu clase, por lo que u = [esta cosa interesante] y v = [esta cosa interesante] también son condiciones posteriores ), pero es lo más obvio.u + 1 = vbreak
u + 1 ≠ vu = [esta cosa interesante]v = [esta cosa interesante]
Ahora, para encontrar otras propiedades interesantes, no hay una receta general. De hecho, hay un sentido formal en el que no hay una receta general para encontrar invariantes de bucle. Lo mejor que puede hacer es aplicar algunas técnicas que solo funcionan en algunos casos, o generalmente ir a pescar para observaciones interesantes (que funciona mejor y mejor a medida que adquiere más experiencia).
Si ejecuta el ciclo durante algunas iteraciones con algún valor de , verá eso en cada iteración:norte
- u salta hasta ( u + v ) / 2 ;tu( u + v )/ 2
- o salta a ( u + v ) / 2 .v( u + v ) / 2
En particular, comienza menos que v , y nunca lo superará. Además, u comienza positivo y aumenta, mientras que v comienza en n + 1 y disminuye. Entonces 0 ≤ u ≤ v ≤ n + 1 es una invariante en todo este programa.tuvtuvn + 10 ≤ u ≤ v ≤ n + 1
Una cosa que no es tan obvio es si nunca puede ser igual a v . Eso es importante: si u y v alguna vez se vuelven iguales, tendremos x = u = v y el ciclo continuará para siempre. Por lo tanto, debe demostrar que u y v nunca se vuelven iguales para demostrar que el algoritmo es correcto (es decir, no se repite para siempre). Una vez que se ha identificado esta necesidad, es fácil demostrar (lo dejo como ejercicio) que u < v es un bucle invariante (tenga en cuenta que u y v son enteros, por lo que esto es equivalente a utuvtuvx = u = vtuvu < vtuv ).u + 1 ≤ v
Como al final del programa, la condición posterior que le dieron también se puede escribir u 2 ≤ n < v 2 (la parte 0 ≤ u 2 es trivial). La razón por la que queremos una condición posterior como esta, que involucre n , es que queremos vincular el resultado del programa con la entrada n . ¿Por qué esta condición precisa? Estamos buscando algo que sea lo más preciso posible, y observamos dónde aparece n dentro del bucle:v = u + 1tu2≤ n < v20 ≤ u2nortenortenorte
- tenemos ;u ≤ x ≤ v
- cuando , elegimos la siguiente u para que sea x , de modo que u 2 ≤ n (y v no cambie);X2≤ ntuXtu2≤ nv
- cuando , elegimos la siguiente v para que sea x , de modo que n < v 2 ( yu no cambie).X2> nvXn < v2tu
Esta dicotomía sugiere que quizás todo el tiempo. En otras palabras, sospechamos que es un bucle invariante. Verificar esto se deja como un ejercicio para el lector (recuerde verificar que la propiedad sea verdadera inicialmente).tu2≤ n < v2
Y ahora que hemos hecho todo esto, vemos que y ( u + 1 ) 2 > n : u es la raíz cuadrada de n redondeado hacia abajo al entero más cercano.tu2≤ n( u + 1 )2> ntunorte