是否需要在循环前后都定义循环不变量?

Does a loop invariant need to be defined both before and after the loop?

到目前为止,我一直对循环不变量及其特定属性感到困惑。它们是否需要在循环之前和之后都为真?或者只是在循环体本身的某个点?

例如:

int sum = 0;
for (int = 0; i < 10; i++) {
    sum += i
}

不变量是总和等于 0 + 1 + 2 + ... + i。您可以说在第二次迭代结束时 i = 1,sum = 1。这行得通,但不变量也需要在迭代开始时有效 - 但事实并非如此。在循环开始之前总和为 0,违反了该不变量。对吗?

循环不变量不属于整个循环,而是属于循环中的一个特定点。你会写一个循环不变式,它在总和增加之前为真,一个在总和增加之后为真,一个在 i 增加之后为真。

当你遍历循环的语句时,你会得到不同的不变量。当您重新进入循环时,循环结束处的那个应该导致循环开始处的那个正确。

是的,循环不变式需要在循环之前和之后都定义并为真。

这是完整的注释代码。为清楚起见,我们已将 for 循环转换为 while。我们定义一个空和 (i-1<0) 为 0:

int sum = 0;
// sum == 0
int i= 0;
// Loop invariant: sum == 0 + 1 + ... i-1
while (i < 10) {
    // Loop invariant: sum == 0 + 1 + ... i-1
    sum += i;
    // sum == 0 + 1 + ... i
    i++;
    // Loop invariant: sum == 0 + 1 + ... i-1
}
// Loop invariant: sum == 0 + 1 + ... i-1, and i == 10 => sum == 0 + 1 + ... 9

如你所见,循环不变量是sum == 0 + 1 + ... i-1。它在循环之前(平凡地)建立,在循环中修改然后恢复,在循环之后为真。与循环退出条件(i == 10)一起保证正确性(sum == 45).