2016-09-26 81 views
0

所以我有這個功能在這裏,我似乎不能理解爲什麼它不會工作。遞歸函數不起作用

let rec recSum n = 
    if n <= 0 then 
    0 
    else 
    recSum n*(n+1)/2 
recSum 4 

我沒有得到一個錯誤,它只是崩潰。任何人都可以找到錯誤?我一直在這裏主演這麼久。

我需要它是遞歸的。

好了,所以我把它改爲:

let rec recSum n = 
if n > 0 then 
    recSum n*(n+1)/2 
else 
    n 
n 
recSum 4 

因爲隨着你們指出,第n只會增加。現在我得到錯誤'FS0001:類型單位不符合int?

+0

你能澄清你想要完成什麼嗎?如下所述,這是無限遞歸,因此您需要實現一個不同的公式,如果我們有關於需求的更多細節,也許我們可以幫助找出一個新的公式。 – EJoshuaS

+1

終止所有已知輸入的類似過程是[Collat​​z猜想](https://en.wikipedia.org/wiki/Collat​​z_conjecture)核心的功能:*半或三加一*。我不確定你的棧的限制是多少,但是如果你可以堆棧1228個函數調用,你可以在任何輸入達到1000億時達到0。 –

回答

1

永遠不會滿足終止條件,所以這是無限遞歸。 (我真的很驚訝,沒有堆棧溢出異常)。終止條件是當n = 0,但每一個遞歸調用只是增加了1:n*(n+1)/2

另外,你的意思是包括乘法作爲參數傳遞給下一個遞歸調用,而不是像

n * recSum (n+1)/2 

東西(請原諒,如果語法不完美,我不在IDE的前面)。

也許你打算減去而不是添加?

作爲一個小題外話,你最終選擇什麼樣的終止條件取決於你想要完成什麼以及你試圖實現什麼樣的公式。很多人都認爲從現在的價值「下降」到終止條件。例如,如果您在談論斐波納契數字,大多數人會認爲這只是「前兩個斐波納契數字的總和」(兩者都是前兩個斐波納契數字的總和,全部方式「下降」到終止條件)。這是完全正確的;例如,定義5是完全正確的!爲5 * 4 !.

您也可以將其視爲終止條件下的「後處理」。這樣想一想:如果我讓你告訴我10的價值!你幾乎肯定無法告訴我沒有使用計算器的價值。但是,如果我告訴你那9!是362880?那麼,你顯然可以乘以10來得到10!所以顯然答案必須是3628800。既然如此,什麼是11!?顯然,11 * 3628800。所以,如果我給你一個價值,你可以使用該值來「生成」更多的價值。給定9!的值,除了乘以10得到10!之外,你不需要做任何事情。

對於這個問題,實際上,鑑於你對10事實的瞭解! = 3,628,800,你可以輕鬆計算9!除以3,628,800除以10.

無論採用哪種方式,點都是一樣的:給定序列中的任何值,就可以應用這些值來計算序列中的更多值。

從這個意義上講,你可以實際上稱終止條件爲我猜測的排序的「初始條件」。

希望這種離題有道理,如果沒有,我會很樂意根據需要澄清它。

+0

傳遞給recSum的值隨着遞歸迅速增加。也許該值超過了變量類型的容量,導致某種分配失敗,在堆棧溢出之前? –

+0

@JuanTomas是的,這似乎是一種可能性,我想知道是否有其他故障發生(或者如果編譯器正在做一些優化「底層」,防止溢出異常,也許將其轉換爲循環或者什麼東西;一個無限循環顯然不會導致堆棧溢出異常本身)。 – EJoshuaS

+0

我編輯了代碼,但現在我又遇到了另一個錯誤。在上面發佈。 – kthonenice

5

問題是,n*(n+1)/2導致遞歸值不斷遞增。沒有辦法得到n <= 0。該序列開始:

4 -> 10 -> 55 -> etc...

傳遞給recSum將只增加值。