如何证明算法正确性?

时间:2019-01-24 18:01:47

标签: java algorithm correctness

我在Java练习中遇到问题,我不明白如何在Java中证明这种求和方法

这就是我做的:

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;
} 

3 个答案:

答案 0 :(得分:1)

循环不变式应表示r等于从索引a到索引0的{​​{1}}元素之和,已排除。即i

然后我们可以注释

r = Sum(k<i: a[k])

证明的关键是

    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]) */

表示总和是递增获得的。

答案 1 :(得分:0)

最简单的方法是定义一组输入及其预期输出。如果这是一项练习,可能会给您这些值,或者您可能需要手工计算其中的几个。然后,我将使用那些已知的输入编写单元测试,以查看每个输出是否与期望值匹配。如果找到不匹配的地方,请再次检查算法期望值。并排进行每个步骤,找出哪个错误(或是否错误)。

另一个选择是用另一种语言编写相同的算法;理想情况下,您不能复制粘贴算法的实现以防止共享常见错误。然后使用 ton 输入运行两者。如果两种实现的每个输入都具有匹配的结果,则您可以更有把握地确信两者都是正确的。

第三个选择是找到一组不变式,即在算法的各个阶段证明是正确的事物。然后在所有表明不变量成立的点上编写测试(或仅抛出assert语句)。诸如for every iteration of the "i" loop, r' >= r之类的东西。然后针对大量输入运行它,如果这些断言中的任何一个失败,则可以开始挖掘并找出忘记在算法中处理的边沿情况(例如,如果输入为空,该怎么办?如何处理负数?数字?等)

答案 2 :(得分:0)

证明您的算法具有预期响应的一种可能性是使用单元测试进行覆盖。

@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);
}

我已经将 assertj 库用于Java测试