我想更多地了解函式中的終止,例如:當 n 是自然數時,終止如何在此函式中作業或如何終止此函式
sum :: Int -> Int
sum 0 = 0
sum n = n sum (n - 1)
uj5u.com熱心網友回復:
遞回代碼的作業原理是這樣的 - 有兩個子句,一個根據自身定義自己,另一個通過回傳單個值來終止計算。這里的終止子句是sum 0 = 0, 的定義由sum給出sum n = n sum (n-1)。
你可以用筆和紙算出來,引數 n = 5:
n sum
5 5 sum (4)
5 4 sum (3)
5 4 3 sum (2)
5 4 3 2 sum (1)
5 4 3 2 1 sum (0)
5 4 3 2 1 0
因為我們指定 sum (0) 為 0,所以計算到此結束。
由于多種原因,計算可能會出錯并且永遠不會終止:
- 沒有終止條款
- 終止條款從未達成
如果您愿意,請考慮以下邪惡的代碼:
badSum :: Int -> Int
badSum 6 = 6
badSum n = n badSum (n-1)
badSum 5 -- locks up, press Ctrl-C
因為永遠不會到達終止子句,所以遞回永遠不會終止。另外,對于你sum和非法值 n = -1。
順便說一句,Haskell 有兩種基本的整數型別,Int和Integer. 型別Int是長整數,而是Integer無限整數。Int速度更快,但Integer可能更適用于遞回,特別是在答案增長非常快的情況下 - 例如階乘。您必須從一種型別轉換(轉換)到另一種型別,因為 Haskell 不會為您執行此操作。在這種情況下,toInteger從投Int到Integer,更普遍fromIntegral。
fact :: Int -> Int
fact 1 = 1
fact n = n * fact (n-1)
fact2 :: Int -> Integer
fact2 1 = 1
fact2 n = (toInteger n) * fact2 (n-1)
在這兩種情況下,階乘都是根據自身定義的,終止子句為 n = 1,結果為 1。兩者都做了合理的作業,但對于較大的 n,fact確實開始表現得很奇怪:
n fact fact2
1 1 1
5 120 120
10 3628800 3628800
20 2432902008176640000 2432902008176640000
30 -8764578968847253504 265252859812191058636308480000000
因為Int是一個固定長度的整數,最終該值將環繞,在這種情況下產生一個負值。
最后,現實世界的 Haskell 不會使用這樣的遞回。您的代碼已臨時替換了 sum 函式。從 1 到 n 的總和由 給出sum [1 .. n],階乘由 給出product [1 .. n]。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/402014.html
上一篇:如何總結for回圈中的所有答案?
