循环不变证明理解

时间:2013-10-03 16:51:10

标签: c loops loop-invariant

我正在尝试学习C中的循环不变量。我有一个代码,我有循环不变量,但我不完全理解为什么。这是代码:

/* 0 ≤ m < n < ASIZE AND A[m] ≥ A[m+1] ≥ ... ≥ A[n] */
void ReverseArray(int A[], int m, int n)
{
  int temp;
  while (m < n)
  {
        temp = A[m]; A[m] = A[n]; A[n] = temp;
        m++;
        n--;
        /* loop invariant: 0 < m < n < ASIZE OR m == n OR m == n+1 */
} 
}
/* for the initial values of m and n, A[m] ≤ A[m+1] ≤ ... ≤ A[n] */

循环不变量为:0&lt; m&lt; n&lt; ASIZE OR m == n OR m == n + 1

我想我明白了0&lt; m&lt; n&lt; A大小。这将是因为w​​hile循环并且它表示m不能为0但它必须小于n。并且n必须小于数组大小。

但我不明白为什么m == n和m == n + 1。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

  

但我不明白为什么m == n和m == n + 1。

在找到循环不变量时,此表达式(循环不变)保证为真:

0 < m < n < ASIZE OR m == n OR m == n+1

但是,这个(“你理解的部分”)总是如此:

0 < m < n < ASIZE

为什么呢?由于m递增,n会递减,因此m < n可能不再为真。

这就是为什么你需要“放大”循环不变量以使它始终为真,包括这些情况,m == nm == n+1,这可能在正常情况下出现执行循环。

所以,如果你说不变量就是“你理解的部分”,你就错了 - 你的循环不变会失败,这是(根据定义)一个禁忌。

答案 1 :(得分:1)

记下2个程序的例子 - 对于偶数和奇数长度的数组。例如,在itera之前创建一个包含迭代次数,数组和值mn的表。我相信最简单的方法就是自己动手并逐行执行代码(表本身对于理解整个问题可能没那么有用)。

PS。不变量似乎太弱而不能建立后置条件。

答案 2 :(得分:1)

如果在循环体之前,就是m + 1 == n的情况,那么在循环结束时,m将递增,n将递减。那时,m == n + 1

例如,当m的值为2时,n的值为3.然后m++; n--;后,m的值为3,{{1} }具有值2.

如果在循环体之前,则是n,然后是循环体m + 2 == n之后的情况。例如,如果m == n的值为2且m的值为4,那么n为3,m为3。

对于在循环体之后结果为nm == n的情况中的任何一种情况,循环控制将为假,因此该情况​​将导致循环停止。