Scala 的阶乘

问题描述

我是 Scala 的新手,想了解递归和尾递归。当我用单行编写程序时,它总是给我 StackOverflow 错误,即使 n=1 -

object Recursion extends App {
   def factorial(n: Int): Int = //if (n<=1) 1
     n * factorial( n - 1 )


  println( factorial( 1 ) )

}

对比

object Recursion extends App {

  def factorial(n: Int): Int = (

    if (n <= 1) 1
    else n * factorial( n - 1 )
    )

  println( factorial( 8 ) )
}

给出正确的值 - 40320

解决方法

明白了,没有if (n<=1),它会无限循环。这就是为什么它永远不会出现并给出此错误的原因。

,

在通过递归解决的问题中,您必须有一个“分支/条件”来中断递归并返回累积值(也就是弹出堆栈),否则问题理论上永远不会停止;实际上,所有对该函数的调用最终都会重载为堆栈分配的内存(即 StackOverflow 错误)

另请注意,您的函数是递归的,但它不是尾递归。要使其成为递归,递归调用必须是最后一步。

要使其尾递归,您必须执行以下操作:

def factorial(n: Int): Int = {
  @tailrec
  def helper(n: Int,acc: Int): Int = {
    if (n == 1) acc
    else helper(n-1,n*acc)
  }
  helper(n,1)
}

就您而言,最后一步是乘法 n*factorial(n-1)。就我而言,这确实是对自己的一种呼唤。

为了清楚起见,在我的示例中,factorial 不是递归的(尾递归或其他),但内部函数 helper 是尾递归的。