简体   繁体   English

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

[英]How to avoid StackOverFlow error in Java/Kotlin/IntelliJ IDEA?

I want to do a factorial of a BigInteger (in Kotlin). 我想做一个BigInteger的阶乘(在Kotlin中)。 With a tail recursion I get StackOverFlow error when I try to do 9000! 使用尾部递归时,当我尝试执行9000时会出现StackOverFlow错误 . With a non-recursive function I can do that ... but I'm very curious how to avoid this kind of error. 使用非递归函数,我可以做到这一点……但是我很好奇如何避免这种错误。

Here is my code: 这是我的代码:

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))}")
}

This is a problem that must solved at the language level, because the JVM does not optimize tail recursion. 这是必须在语言级别解决的问题,因为JVM不会优化尾递归。

Fortunately, the Kotlin language provides a tailrec modifier for exactly this purpose, so you can simply write tailrec fun instead of fun . 幸运的是,Kotlin语言为此目的提供了一个tailrec修饰符,因此您可以简单地编写tailrec fun而不是fun The compiler will convert tail calls inside a tailrec function into loops, which should get rid of the stack overflow you are experiencing. 编译器会将tailrec函数内的尾部调用转换为循环,这将消除您遇到的堆栈溢出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM