【问题标题】:Why is this tail recursive?为什么这个尾递归?
【发布时间】:2011-03-17 09:29:14
【问题描述】:

查看这个 Scala 代码:

def rec(n: Int) {
  if (n > 1) {
    val d = n / 2
    rec(d)
//    if (d > 1)  // abort loop
      rec(n/d)
  }
}

此代码将导致无限循环。由于尾递归优化,我没有收到 StackOverflowError。

用 jad 反编译我得到了这个 Java 代码:

public void rec(int n)
{
    int d;
    for(; n > 1; n /= d)
    {
        int i = n;
        d = i / 2;
        rec(d);
    }
}

在循环的最后一行,该方法调用自身,因此我不了解尾调用位置。谁能解释一下?

【问题讨论】:

标签: scala tail-recursion


【解决方案1】:

rec(d) 没有尾调用。对于rec(N)(其中N > 1)堆栈在log2(N) 调用后不再增长(因为在那之后n 永远等于2 或3,而d 是1)。之后,它只是带有内部rec(1) 调用的无限循环,每次都会立即返回。这就是为什么没有堆栈溢出。

【讨论】:

    【解决方案2】:

    在您的方法的递归形式中,您有两个递归调用。 StackOverflowError 是由它们中的最后一个引起的。

    由于尾​​递归优化,最后一次调用变成循环(而第一次调用保持递归),因此你有无限循环而不是无限递归,StackOverflowError 不会发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多