我在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;
}
答案 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测试