Multiplication of numbers in a sequence,
for i in range(1, n + 1):
r *= i
return r
creates a large number (as in tens of thousands of bits) very quickly, and then you have many multiplications by one huge number and one small number. Multiplications, when at least one of the factors is huge, is slow.
You can speed it up significantly by reducing the number of multiplications including huge numbers, like
def range_prod(lo,hi):
if lo+1 < hi:
mid = (hi+lo)//2
return range_prod(lo,mid) * range_prod(mid+1,hi)
if lo == hi:
return lo
return lo*hi
def treefactorial(n):
if n < 2:
return 1
return range_prod(1,n)
, 100000! % 100019 ( len(str(fun(100000)), , , ):
$ python factorial.py
81430
math.factorial took 4.06193709373 seconds
81430
factorial took 3.84716391563 seconds
81430
treefactorial took 0.344486951828 seconds
10 × 100000!.