3

I am researching on speed of factorial. But I am using two ways only,

import timeit

def fact(N):
    B = N
    while N > 1:
        B = B * (N-1)
        N = N-1
    return B

def fact1(N):
    B = 1
    for i in range(1, N+1):
        B = B * i
    return B


print timeit.timeit('fact(5)', setup="from __main__ import fact"), fact(5)
print timeit.timeit('fact1(5)', setup="from __main__ import fact1"), fact1(5)

Here is the output,

0.540276050568 120
0.654400110245 120

From above code I have observed,

  1. While take less time than for

My question is,

Is the best way to find the factorial in python ?

4
  • Use a larger number N so you are testing the loop and not the function overhead. Commented Dec 16, 2013 at 5:42
  • Why do N-1 twice? You can swap those two lines and save one subraction Commented Dec 16, 2013 at 5:52
  • Do you want to find a more effective algorithm ? Commented Dec 16, 2013 at 6:46
  • @yes atupal. I want much effective algorithm Commented Dec 16, 2013 at 12:29

4 Answers 4

12

If you're looking for the best, why not use the one provided in the math module?

>>> import math
>>> math.factorial
<built-in function factorial>
>>> math.factorial(10)
3628800

And a comparison of timings on my machine:

>>> print timeit.timeit('fact(5)', setup="from __main__ import fact"), fact(5)
0.840167045593 120
>>> print timeit.timeit('fact1(5)', setup="from __main__ import fact1"), fact1(5)
1.04350399971 120
>>> print timeit.timeit('factorial(5)', setup="from math import factorial")
0.149857997894

We see that the builtin is significantly better than either of the pure python variants you proposed.

Sign up to request clarification or add additional context in comments.

Comments

4

TLDR; microbenchmarks aren't very useful

For Cpython, try this:

>>> from math import factorial


>>> print timeit.timeit('fact(5)', setup="from __main__ import fact"), fact(5)
1.38128209114 120
>>> print timeit.timeit('fact1(5)', setup="from __main__ import fact1"), fact1(5)
1.46199703217 120
>>> print timeit.timeit('factorial(5)', setup="from math import factorial"), factorial(5)
0.397044181824 120

But under pypy, the while is faster than the one from math

>>>> print timeit.timeit('fact(5)', setup="from __main__ import fact"), fact(5)\
0.170556783676 120
>>>> print timeit.timeit('fact1(5)', setup="from __main__ import fact1"), fact1\
(5)
0.319650173187 120
>>>> print timeit.timeit('factorial(5)', setup="from math import factorial"), f\
actorial(5)
0.210616111755 120

So it depends on the implementation. Now try bigger numbers

>>>> print timeit.timeit('fact(50)', setup="from __main__ import fact"), fact(50)
7.71517109871 30414093201713378043612608166064768844377641568960512000000000000
>>>> print timeit.timeit('fact1(50)', setup="from __main__ import fact1"), fact1(50)
6.58060312271 30414093201713378043612608166064768844377641568960512000000000000
>>>> print timeit.timeit('factorial(50)', setup="from math import factorial"), factorial(50)
6.53072690964 30414093201713378043612608166064768844377641568960512000000000000

while is in last place, and the version using for is about the same as the one from the math module

Comments

1

Otherwise, if you're looking for a Python implementation (this is my favourite):

from operator import mul


def factorial(n):
    return reduce(mul, range(1, (n + 1)), 1)

Usage:

>>> factorial(0)
1
>>> factorial(1)
1
>>> factorial(2)
2
>>> factorial(3)
6
>>> factorial(4)
24
>>> factorial(5)
120
>>> factorial(10)
3628800

Performance: (On my desktop:)

$ python -m timeit -c -s "fact = lambda n: reduce(lambda a, x: a * x, range(1, (n + 1)), 1)" "fact(10)"
1000000 loops, best of 3: 1.98 usec per loop

Comments

0

I have tried with reduce(lambda x, y: x*y, range(1, 5))

>>>timeit("import math; math.factorial(4)")
1.0205099133840179

>>>timeit("reduce(lambda x, y: x*y, range(1, 5))")
1.4047879075160665

>>>timeit("from operator import mul;reduce(mul, range(1, 5))")
2.530837320051319

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.