2017-09-04 25 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 –