如何避免Java / Kotlin / IntelliJ IDEA中的StackOverFlow错误?
我想做一个BigInteger的阶乘(在Kotlin中)。 有了尾递归,当我尝试做9000时,会出现StackOverFlow错误! 。 有了一个非递归函数,我可以做到这一点…但我很好奇如何避免这种错误。
这是我的代码:
import java.math.BigInteger fun tail_recursion_factorial(n: BigInteger, factorialOfN: BigInteger = BigInteger.valueOf(2)): BigInteger { return when(n){ BigInteger.ONE -> BigInteger.ONE BigInteger.valueOf(2) -> factorialOfN else -> tail_recursion_factorial(n.minus(BigInteger.ONE), n.times(factorialOfN)) } } fun non_recursive_factorial(n: BigInteger): BigInteger{ var i: BigInteger = BigInteger.ONE var factorial: BigInteger = BigInteger.ONE while (i<=n){ factorial = factorial.times(i) i = i.plus(BigInteger.ONE) } return factorial } fun main(args: Array<String>){ print("n == ") var n = readLine()!! //recursive //println("$n! is ${tail_recursion_factorial(BigInteger(n))}") //non-recursive println("$n! is ${non_recursive_factorial(BigInteger(n))}") }
这是一个必须在语言层面解决的问题,因为JVM不会优化尾递归。
幸运的是,Kotlin语言完全提供了tailrec
修饰符,因此您可以简单地写tailrec fun
而不是fun
。 编译器会将tailrec函数中的tail调用转换成循环,这应该消除你正在经历的堆栈溢出。