Scala中的尾递归函数出错以找到第n个Fibonacci数

时间:2016-06-10 02:48:11

标签: scala fibonacci tail-recursion

我想实现一个尾递归函数来获取 n 的Fibonacci数。

这是我的尝试。它并不像 n = 4或更高版本那样工作。

object Fibonacci {
    def fib(n: Int): Int = {
        def go(n: Int, acc: Int): Int =
            if (n <= 1) 0 + acc
            else if (n == 2) 1 + acc
            else go(n-1, go(n-2, 0))
        go(n, 0)
    }
}

问题是,当输入 n = 3时,所需的输出为1,输入 n = 4或更高仍然只返回1.

我注意到的是,如果我定义了另一行&#34;否则如果&#34;,即如果(n == 3)1 + acc,那么我的函数将按预期用于 n < / em> = 4(它将返回&#34; 2&#34;正如预期的那样),但它仍然不适用于 n = 5或更高,我可以&#39;弄清楚原因。

如果我对这个问题的解决方法看起来很奇怪,那是因为这是我到目前为止学到的所有内容,而且应该足以解决手头的问题。

实际上,我并不完全确定上述函数是否可以被视为尾递归,因为我刚刚开始学习它。如果不是,请指出我,我会做出相应的更改。

3 个答案:

答案 0 :(得分:3)

您的代码不是尾递归的,因为它在最里面的go()调用中构建了一个堆栈。

解决方案是将帮助者扁平化以包括前两个术语(不只是一个术语):

def fib(n : Int) : Int = { 
  def go(n: Int, acc:Int, x:Int): Int = n match {
    case 0 => acc 
    case _ => go(n-1, x, acc+x)
  }
  return go(n, 0, 1)
}

答案 1 :(得分:0)

你的问题是,在n> 2的情况下,你没有使用&#39; acc&#39;参数。

当你打电话给go(4,0)时,你得到:go(3,go(2,0))

go(2,0)解析为1,所以你调用go(3,1),转为go(2,go(1,0))

go(1,0)resovles to 0,所以你调用go(2,0),返回1.

你需要你的最后一个案例来阅读:go(n-1,go(n-2,acc))

正如其他人所说,你的函数不是尾递归的,因为调用go(n-2,0)的结果用于另一个函数调用。如果你打算做一个尾递归函数,请使用&#39; @ tailrec&#39;注释,这样当函数不是尾递归时,编译器会给你一个错误。

理查德的解决方案是在循环周围运行两个累加器:当前总数和前一个总数,最后将其中一个累加出来,从而允许函数正确地尾递归。

答案 2 :(得分:0)

此解决方案始终返回 n 斐波纳契数而不是n + 1斐波纳契数。

def fibonacci (n: Int): Int = {

    @tailrec
    def go(nextToLast: Int, last: Int, n: Int): Int = n match {
        case 0 => 0
        case 1 => last
        case _ => go(last, nextToLast+last, n-1)
    }
    go(0, 1, n-1)
}

我希望能帮助