迴圈是程式語言中最強大的指令之一,在迴圈中不管是多複雜的運算,我們想讓電腦執行100次或100億次,也不過是更動一個數字的差別而已。

不過,對初學者來說,撰寫迴圈很容易出錯,以下三個範例程式都有些「小毛病」(稱為bug臭蟲),請動手試試看,你能夠找出bug嗎?

// 1-2c Debug exercise #1
// Created by Heman, 2021/07/09
// 求1到100整數和
var 總和 = 0
for i in 1...100 {
    總和 = 總和 + i
}
print(i, 總和)

還記得什麼叫「迴圈參數」嗎?最後一行會造成什麼錯誤?

// 1-2d Debug exercise #2
// Created by Heman, 2021/07/09
let 寬 = 0.5
var x = 0.0, y = 0.0, 總和 = 0.0

while x < 100.0 {
    y = x
    總和 = 總和 + y * 寬
    print(x, 總和)
    x = x + 寬
}
print(總和)

1-2d 程式可以執行,但是結果差一點點,不盡人意,為什麼?

因為迴圈最後一次執行,x = 99.5時, 因為我們先加總,再遞增x,所以下一次 x 變成100.0 時,已經不再是 x < 100.0,達成脫離迴圈的條件,結果總和就少加了一筆。

這種稱為「邊界條件(Boundary condition)」的問題,所謂「邊界條件」指的是第一次進入迴圈以及最後一次要脫離迴圈的條件,這會影響 { } 裡面程式碼的順序或邏輯,所以寫迴圈時務必要檢查邊界條件的情況。

// 1-2e Debug exercise #3
// Created by Heman, 2021/07/09
let 寬 = 0.5
var x = 0.0, y = 0.0, 總和 = 0.0

while x < 100.0 {
    y = x
    總和 = 總和 + y * 寬
    print(x, 總和)
}
print(總和)

1-2e 程式可以執行,但是差了關鍵的一行,結果會造成很大的問題,稱為「無窮迴圈」,也就是說,永遠達不到脫離迴圈的條件,在此例中,脫離迴圈的條件是 x 大於或等於100.0,但是 x 沒有遞增,就永遠不會大於或等於100.0。

這是 while 迴圈以及另一個 repeat 迴圈特別要注意的問題。for 迴圈因為必須先界定好範圍,比較安全,不會造成無窮迴圈。

可見迴圈雖然是重複相同的工作,但其實每一次重複都有一點點差異,而且這點差異,必須能夠累積到達脫離迴圈的條件,否則就會造成無窮迴圈,變成瞎忙空轉。

這個邏輯其實跟宇宙運行的道理一模一樣,太陽雖然每天都是從東邊升起、西邊落下,但其實每天角度都有點微小差異,就是這點感覺不到的差異,造就地球的春夏秋冬以及豐富的生態。難怪古人說:「天行健,君子以自強不息」,我們每天學點新東西,多一些小改變,就能讓自身變強變好。