c# - Way to get around stack size -
have recursive factorial function in c#. using deal biginteger
. problem arises when want deal large integers , because function recursive cause stackoverflow
exception. simple solution not make function recursive. wondering if there way around this? i'm thinking along lines of more ram allocated the stack?
biginteger factorial(biginteger n) { return n == 1 ? 1 : n * factorial(n - 1); }
i understand nice if express recursive functions in c# without worrying stack. unfortunately not directly possible, , no matter how big make stack there situations run out of stack space. furthermore performance pretty horrendous. if have tail recursive function factorial can done, pretty lets express function in original recursive way, without huge penalty.
unfortunately c# not directly support tail recursive calls, workarounds possible using so-called "trampoline" construction.
see example: http://bartdesmet.net/blogs/bart/archive/2009/11/08/jumping-the-trampoline-in-c-stack-friendly-recursion.aspx , http://www.thomaslevesque.com/2011/09/02/tail-recursion-in-c/
from last blog, comes following code allow perform factorial tail recursive function without stack problems.
public static class tailrecursion { public static t execute<t>(func<recursionresult<t>> func) { { var recursionresult = func(); if (recursionresult.isfinalresult) return recursionresult.result; func = recursionresult.nextstep; } while (true); } public static recursionresult<t> return<t>(t result) { return new recursionresult<t>(true, result, null); } public static recursionresult<t> next<t>(func<recursionresult<t>> nextstep) { return new recursionresult<t>(false, default(t), nextstep); } } public class recursionresult<t> { private readonly bool _isfinalresult; private readonly t _result; private readonly func<recursionresult<t>> _nextstep; internal recursionresult(bool isfinalresult, t result, func<recursionresult<t>> nextstep) { _isfinalresult = isfinalresult; _result = result; _nextstep = nextstep; } public bool isfinalresult { { return _isfinalresult; } } public t result { { return _result; } } public func<recursionresult<t>> nextstep { { return _nextstep; } } } class program { static void main(string[] args) { biginteger result = tailrecursion.execute(() => factorial(50000, 1)); } static recursionresult<biginteger> factorial(int n, biginteger product) { if (n < 2) return tailrecursion.return(product); return tailrecursion.next(() => factorial(n - 1, n * product)); } }