如何避免 Java/Kotlin/IntelliJ IDEA 中的 StackOverFlow 错误?
How to avoid StackOverFlow error in Java/Kotlin/IntelliJ IDEA?
我想计算 BigInteger 的阶乘(在 Kotlin 中)。
使用尾递归,当我尝试执行 9000! 时出现 Whosebug 错误。
使用非递归函数我可以做到这一点......但我很好奇如何避免这种错误。
这是我的代码:
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 函数内的尾部调用转换为循环,这应该会消除您遇到的堆栈溢出问题。
我想计算 BigInteger 的阶乘(在 Kotlin 中)。 使用尾递归,当我尝试执行 9000! 时出现 Whosebug 错误。 使用非递归函数我可以做到这一点......但我很好奇如何避免这种错误。
这是我的代码:
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 函数内的尾部调用转换为循环,这应该会消除您遇到的堆栈溢出问题。