java - 如何避免 Java/Kotlin/IntelliJ IDEA 中的 StackOverFlow 错误?

标签 java recursion kotlin tail-recursion

我想计算 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 函数内的尾部调用转换为循环,这应该会消除您遇到的堆栈溢出。

关于java - 如何避免 Java/Kotlin/IntelliJ IDEA 中的 StackOverFlow 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46039118/

相关文章:

java - sendRedirect() 问题

java - 链接到 sqlite 数据库的注册按钮

c++ - 我对骑士之旅的实现是无效的,可能是错误的递归调用

arrays - 如何使用扩展运算符将 Array<Int> 传递给 vararg Int 函数?

kotlin - Kotlin扩展功能-覆盖现有方法

java - 如何在普通的非 Android Java 应用程序中使用 NDK 编译的 JNI 库?

recursion - 计算递归关系 T(n)=T(n-1)+logn

Javascript 使用函数的输出作为自己的输入

java - Debug模式在带有 Kotlin 的 IDEA 中停止工作

java - 使用 xsl 和 java 样式将 xml 转换为 html 时,包含 html 数据的 Xml 元素消失