[英]How can I prove algorithm correctness?
I have a problem with this exercise in Java, I don't understand how to prove this sum method in Java我在 Java 中的这个练习有问题,我不明白如何在 Java 中证明这个 sum 方法
This is what I made :这是我做的:
P(0) : If r=0 and i=0 => r=0+a[0]
p(i+1) : r'= r + a[i] and i'=i+1
r'=r + a[i] + a[i+1]
public static int sum(int[] a) {
int r = 0;
int i = 0;
while (i < a.length) {
r = r + a[i];
i = i + 1;
}
return r;
}
The loop invariant should express that r
equals the sum of the elements of a
from index 0
to index i
, excluded.循环不变量应该表示
r
等于a
从索引0
到索引i
的元素之和,不包括在内。 Ie r = Sum(k<i: a[k])
.即
r = Sum(k<i: a[k])
。
Then we can annotate然后我们可以注释
int r = 0;
int i = 0;
/* r = Sum(k<i: a[k]) */
while (i < a.length) {
r = r + a[i];
/* r = Sum(k<i: a[k]) + a[i] = Sum(k<i+1: a[k]) */
i = i + 1;
/* r = Sum(k<i: a[k]) */
}
/* r = Sum(k<=a.length: a[k]) */
The crux of the proof is证明的关键是
Sum(k<i: a[k]) + a[i] = Sum(k<i+1: a[k])
expressing that the sum is obtained incrementally.表示总和是递增获得的。
The easiest method is to define a set of inputs along with their expected outputs.最简单的方法是定义一组输入及其预期输出。 If this is for an exercise, you may be given these values, or you may need to calculate a handful of them by hand.
如果这是用于练习,您可能会获得这些值,或者您可能需要手动计算其中的一些值。 Then I would write unit tests using those known inputs to see if each output matches the expected value.
然后我将使用这些已知输入编写单元测试,以查看每个输出是否与预期值匹配。 If you find places where they don't match, double check both your algorithm and the expected values.
如果您发现它们不匹配的地方,请仔细检查您的算法和预期值。 Work through the steps of each side-by-side and figure out which one is wrong (or if both are wrong).
并排完成每个步骤并找出哪个是错误的(或者两者是否都错误)。
Another option is to write the same algorithm in another language;另一种选择是用另一种语言编写相同的算法; ideally, one where you can't copy-paste the algorithm's implementation to prevent sharing common bugs.
理想情况下,您不能复制粘贴算法的实现以防止共享常见错误。 Then run both with a ton of inputs.
然后使用大量输入运行两者。 If both implementations have matching results for every input, you can have a higher confidence that both are correct.
如果两个实现对每个输入都有匹配的结果,您就可以更有把握地认为两者都是正确的。
A third option is to find a set of invariants, ie things that are provably true at various stages of the algorithm.第三种选择是找到一组不变量,即在算法的各个阶段可证明为真的事物。 Then write tests (or just throw in
assert
statements) at all of those points that show that the invariants hold.然后在所有那些表明不变量成立的点上编写测试(或只是抛出
assert
语句)。 Things like for every iteration of the "i" loop, r' >= r
. for every iteration of the "i" loop, r' >= r
之类for every iteration of the "i" loop, r' >= r
事情。 Then run it against a large range of inputs, and if any of those assertions fail, you can start digging in and figuring out what edge case you forgot to handle in your algorithm (eg What if the input is empty? How do I handle negative numbers? etc.)然后针对大范围的输入运行它,如果这些断言中的任何一个失败,您可以开始深入研究并找出您忘记在算法中处理的边缘情况(例如,如果输入为空怎么办?我如何处理否定数字?等)
One of the possibilities that prove that your algorithm has an expected response is to cover it with unit tests.证明您的算法具有预期响应的可能性之一是用单元测试覆盖它。
@Test
public void sumWorksFineWithNaturalValues() {
int[] input = {1, 2, 3, 4};
int expectedResponse = 10;
assertThat(sum(input)).isEqualTo(expectedResponse);
}
@Test
public void sumCanHandleNegativeValues() {
int[] input = {0, 1, -2, -3, 4};
int expectedResponse = 0;
assertThat(sum(input)).isEqualTo(expectedResponse);
}
@Test
public void sumCanHandleEmptyArray() {
int[] input = {};
int expectedResponse = 0;
assertThat(sum(input)).isEqualTo(expectedResponse);
}
I have used assertj library for java tests我已经将assertj库用于 Java 测试
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.