2017-09-04 54 views
0

我想做一个BigInteger的阶乘(在Kotlin中)。 当我尝试做9000时,发生尾部递归,我得到了StackOverFlow错误!。 使用非递归函数我可以做到这一点...但我很好奇如何避免这种错误。如何避免Java/Kotlin/IntelliJ IDEA中的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))}") 
} 
+0

可能重复的[如何增加Java堆栈大小?](https://stackoverflow.com/questions/3700459/how-to-increase-the-java-stack-size) – konsolas

回答

4

这是一个必须解决在语言层面的一个问题,因为JVM不优化尾递归。

幸运的是,Kotlin语言完全提供了一个tailrec修饰符,因此您只需编写tailrec fun而不是fun。编译器会将tailrec函数中的tail调用转换为循环,这应该消除您遇到的堆栈溢出。

+0

更多信息:https:///kotlinlang.org/docs/reference/functions.html#tail-recursive-functions –