Как избежать ошибки StackOverFlow в Java / Kotlin / IntelliJ IDEA?

Я хочу сделать факториал BigInteger (в Котлине). С хвостом рекурсии я получаю ошибку StackOverFlow, когда я пытаюсь сделать 9000! , С нерекурсивной функцией я могу это сделать … но мне очень любопытно, как избежать такой ошибки.

Вот мой код:

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 от tailrec fun вместо fun . Компилятор преобразует хвостовые вызовы внутри функции tailrec в циклы, которые должны избавиться от переполнения стека, которое вы испытываете.