2016-09-26 66 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将只增加值。