我正在为语言理论考试修改工作。我们可以做的一些练习涉及编写前后条件和循环不变量,用于几种方法。
我已经完成了一个,并认为它非常好(请告诉我,如果不是:P),下一个应该是相似的,但有一个简单的方法来解决它。
int sum(int[] a) //method header
Pre: even(a.length) //precondition
Post: result = SUM(i=0;a.length−1) a[i] //postcondition
int sum(int[] a) {
int r = 0;
int k = 0;
while (k < a.length) {
r = r + a[k];
k = k + 1;
}
return r;
}
我将pre / pos + loop inv设为:
Pre: even(a.length) ∧ r = 0 ∧ k = 0
Post: r = SUM(i=0;a.length−1) a[k]
Inv: 0 ≤ k ≤ a.length ∧ r = SUM(i=0; k −1) a[i]
我需要对这些(非常)类似的方法做同样的事情:
1
int r = 0;
int k = a.length-1;
while (k >= 0 ) {
r = r + a[k];
k = k - 1;
}
return r;
2
int r = 0;
int k = 0;
while (k < a.length/2) {
r = r + a[k] + a[a.length-1-k];
k = k + 1;
}
return r;
3
int r = 0;
int k = 0;
while (k < a.length) {
r = r + a[k] + a[k+1];
k = k + 2;
}
return r;
4
int r = 0; int s = 0;
int k = 0; int l = a.length-1;
while (k < l) {
r = r + a[k]; s = s + a[l];
k = k + 1; l = l - 1;
}
return r + s;
所以基本上我要问的是,我的第一部分是正确的(前/后/循环在顶部),如果是这样,这四个如何变化(似乎并不多)。
提前感谢您的帮助。
[编辑]
尝试Q1(不确定质量)
Pre: even(a.length) ∧ r = 0 ∧ k = a.length-1
Post: r = SUM(a.length−1; i=0) a[k]
Inv: 0 ≤ k ≤ a.length ∧ r = SUM(k-1; i=0) a[i]
答案 0 :(得分:2)
您的r=SUM
应该是r = SUM(i=0;k −1) a[i]
第一个只是向后计数
数字2和4基本等同于l
,4是a.length-1-k
的别名(看看你是否可以证明你自己),它们都来自数组的任一端并从那里求和< / p>
第三个为计数器变量k
增加2,但不变量因此而改变
答案 1 :(得分:1)
有兴趣看到实际的问题,因为......“制定前后条件”是无稽之谈:如果考官要求......改为更好的学校。
你可能会被问到“找到方法终止的最弱前提条件并给出明确定义的答案,在这种情况下是最强的后置条件”:这是一个明智的问题。
另一方面,考虑到第一种方法和所述的前/后条件,询问循环前/后条件和不变量是有意义的,但如上所述,问题应该向后解决:给定预期的方法后置条件,该方法满足后置条件所需的循环最弱条件是什么?
然后:考虑到后置条件,所需的循环最弱的前提条件是什么?鉴于您可以询问是否可以从规定的方法前提条件推断出前提条件(不要忘记方法开始和循环之间的代码)。
在那种形式中,even
谓词没有位置,不需要满足循环或方法的后置条件(这是引用的第一个算法)。
您感兴趣的是,您错过了一些重要的前提条件。其中之一是总和在int
类型的范围内,但是如果溢出导致非终止,则这是不够的。