Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何证明算法的正确性?_Java_Algorithm_Correctness - Fatal编程技术网

Java 如何证明算法的正确性?

Java 如何证明算法的正确性?,java,algorithm,correctness,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] 公共静态整数和(int[]a){ int r=0; int i=0; while(i

我对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]

公共静态整数和(int[]a){
int r=0;
int i=0;
while(i
最简单的方法是定义一组输入及其预期输出。如果这是为了练习,你可能会得到这些值,或者你可能需要手工计算其中的一小部分。然后,我将使用这些已知的输入编写单元测试,以查看每个输出是否与预期值匹配。如果发现不匹配的地方,请仔细检查算法和期望值。并排完成每个步骤,找出哪一个错了(或者两者都错了)

另一种选择是用另一种语言编写相同的算法;理想情况下,您不能复制粘贴算法的实现以防止共享常见错误。然后用大量的输入运行这两个程序。如果两个实现对每个输入都有匹配的结果,那么您就可以对两者都是正确的有更高的信心


第三种选择是找到一组不变量,即在算法的各个阶段都可以证明为真的东西。然后在所有显示不变量的点上编写测试(或者只抛出
assert
语句)。类似于
对于“i”循环的每次迭代,r'>=r
。然后对大范围的输入运行它,如果这些断言中的任何一个失败,您可以开始深入研究并找出您在算法中忘记处理的边缘情况(例如,如果输入为空怎么办?如何处理负数?等等)

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

@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测试

循环不变量应该表示
r
等于
a
从索引
0
到索引
I
的元素之和,不包括在内。即<代码> r=和(您的公式应该返回<代码> r+a[i] +a[i+1] < /Cord> @ dUWEST:测试运行永远不是一个证明。作为提示,考虑P(n)应该是什么。我建议它是数组的长度——在这种情况下,p(0)断言不成立,因为<代码> [0 ] < /C>是未定义的。(在Java中,这是一个IndexOutOfBoundsException)。然后对于P(n+1),您需要断言循环在P(n)中的行为与在P(n+1)中的行为。在这两个循环中,
i
的可能值是什么?它们如何相互映射?这与算法证明无关。唯一的证明方法是覆盖所有可能的输入。这不是一个特别优雅的证明(而且可能不会满足要求此证明的任何人),但这将是一个证明。整数有一个固定的范围,数组有一个最小和最大的大小,所以从技术上讲,这样的证明是可能的。但是作为一个粗略的猜测,我猜如果你每秒写100个这样的测试,你仍然会在太阳死后写它们。@yshavit:我可以原谅你不知道什么是算法证明。我不能原谅你让你相信你知道。@yshavit:这不是向OP提出的要求。你知道的。而仅以两个32位整数作为输入的穷举测试是不可行的(至少需要500年的计算时间)。@YvesDaoust我的评论是开玩笑地说,即使有人试图通过单元测试来证明算法(我明确指出,这不符合OP的要求),这将需要一段不切实际的很长时间,比太阳的存活时间还要长。我并不是想说这样的证明是可行的;我同意你的评论,即测试不是任何真正目的的证明。测试不是证明手段。使用大量输入运行是一种非常幼稚的方法。原因有两个:通常,算法失败在边界情况下,而不是在域内。除非您关注边界,否则大量输入是无用的;否则,大量输入实际上等同于单个情况。即使如此,只要存在少量状态变量,通过任意测试发现错误的概率往往是无穷小的。
@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);
}
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]) */
Sum(k<i: a[k]) + a[i] = Sum(k<i+1: a[k])