簡體   English   中英

如何證明算法的正確性?

[英]How can I prove algorithm correctness?

我在 Java 中的這個練習有問題,我不明白如何在 Java 中證明這個 sum 方法

這是我做的:

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

循環不變量應該表示r等於a從索引0到索引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]) */

證明的關鍵是

Sum(k<i: a[k]) + a[i] = Sum(k<i+1: a[k])

表示總和是遞增獲得的。

最簡單的方法是定義一組輸入及其預期輸出。 如果這是用於練習,您可能會獲得這些值,或者您可能需要手動計算其中的一些值。 然后我將使用這些已知輸入編寫單元測試,以查看每個輸出是否與預期值匹配。 如果您發現它們不匹配的地方,請仔細檢查您的算法預期值。 並排完成每個步驟並找出哪個是錯誤的(或者兩者是否都錯誤)。

另一種選擇是用另一種語言編寫相同的算法; 理想情況下,您不能復制粘貼算法的實現以防止共享常見錯誤。 然后使用大量輸入運行兩者。 如果兩個實現對每個輸入都有匹配的結果,您就可以更有把握地認為兩者都是正確的。

第三種選擇是找到一組不變量,即在算法的各個階段可證明為真的事物。 然后在所有那些表明不變量成立的點上編寫測試(或只是拋出assert語句)。 for every iteration of the "i" loop, r' >= r之類for every iteration of the "i" loop, 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 測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM