This is one of the practical limitations of recursion without tail call optimization.
Python has a guard against the number of recursive calls you can make in order to avoid a stack overflow. This is the RecursionError
you are seeing:
Python 3.7.4 (default, Aug 13 2019, 20:35:49)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def recursion(n):
... return 1 if n < 2 else n * recursion(n - 2)
...
>>>
>>> string = str(recursion(1000000000000000000))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in recursion
File "<stdin>", line 2, in recursion
File "<stdin>", line 2, in recursion
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded in comparison
Increasing is a possible solution, but it only removes the built-in guard. If enough recursive calls are made, you will eventually run out of memory, which is the second error you are getting (MemoryError: Stack overflow
or a segmentation fault in my case).
Python 3.7.4 (default, Aug 13 2019, 20:35:49)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.setrecursionlimit(100000)
>>> def recursion(n):
... return 1 if n < 2 else n * recursion(n - 2)
...
>>> string = str(recursion(1000000000000000000))
Segmentation fault
The idiomatic solution to this problem in Python would be to use iteration instead:
def iteration(n):
result = 1
for i in range(n, 1, -2):
result *= i
return result
Running this example with your original input (1e18
) won't terminate any time soon though. As the integer grows, it takes increasingly more time to compute, because the operations require using integer representations larger than 64-bit (or however many bits your CPU is able to represent with a single register).
Nevertheless, that would be the Pythonic solution to this problem.