MOON
MOON

Reputation: 2811

Factorial in numpy and scipy

How can I import factorial function from numpy and scipy separately in order to see which one is faster?

I already imported factorial from python itself by import math. But, it does not work for numpy and scipy.

Upvotes: 86

Views: 276832

Answers (6)

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 251146

You can import them like this:

In [7]: import scipy, numpy, math

In [8]: scipy.math.factorial, numpy.math.factorial, math.factorial
Out[8]: 
(<function math.factorial>,
 <function math.factorial>,
 <function math.factorial>)

scipy.math.factorial and numpy.math.factorial seem to simply be aliases/references for/to math.factorial, that is scipy.math.factorial is math.factorial and numpy.math.factorial is math.factorial should both give True.

Upvotes: 104

Janne Karila
Janne Karila

Reputation: 25207

SciPy has the function scipy.special.factorial (formerly scipy.misc.factorial)

>>> import math
>>> import scipy.special
>>> math.factorial(6)
720
>>> scipy.special.factorial(6)
array(720.0)

It can handle arrays or array-likes, for example:

>>> scipy.special.factorial([6, 7])
array([ 720., 5040.])
>>> math.factorial([6, 7])
TypeError: 'list' object cannot be interpreted as an integer

Upvotes: 31

sudheer naidu
sudheer naidu

Reputation: 162

enter image description here

after running different aforementioned functions for factorial, by different people, turns out that math.factorial is the fastest to calculate the factorial.

find running times for different functions in the attached image

Upvotes: 2

Stefan Gruenwald
Stefan Gruenwald

Reputation: 2640

from numpy import prod

def factorial(n):
    print prod(range(1, n+1))

or with mul from operator:

from operator import mul

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

or completely without help:

def factorial(n):
    print reduce((lambda x,y: x*y), range(1, n+1))

Upvotes: 7

Yuxiang Wang
Yuxiang Wang

Reputation: 8433

The answer for Ashwini is great, in pointing out that scipy.math.factorial, numpy.math.factorial, math.factorial are the same functions. However, I'd recommend use the one that Janne mentioned, that scipy.special.factorial is different. The one from scipy can take np.ndarray as an input, while the others can't.

In [12]: import scipy.special

In [13]: temp = np.arange(10) # temp is an np.ndarray

In [14]: math.factorial(temp) # This won't work
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-039ec0734458> in <module>()
----> 1 math.factorial(temp)

TypeError: only length-1 arrays can be converted to Python scalars

In [15]: scipy.special.factorial(temp) # This works!
Out[15]: 
array([  1.00000000e+00,   1.00000000e+00,   2.00000000e+00,
         6.00000000e+00,   2.40000000e+01,   1.20000000e+02,
         7.20000000e+02,   5.04000000e+03,   4.03200000e+04,
         3.62880000e+05])

So, if you are doing factorial to a np.ndarray, the one from scipy will be easier to code and faster than doing the for-loops.

Upvotes: 63

SeF
SeF

Reputation: 4188

You can save some homemade factorial functions on a separate module, utils.py, and then import them and compare the performance with the predefinite one, in scipy, numpy and math using timeit. In this case I used as external method the last proposed by Stefan Gruenwald:

import numpy as np


def factorial(n):
    return reduce((lambda x,y: x*y),range(1,n+1))

Main code (I used a framework proposed by JoshAdel in another post, look for how-can-i-get-an-array-of-alternating-values-in-python):

from timeit import Timer
from utils import factorial
import scipy

    n = 100

    # test the time for the factorial function obtained in different ways:

    if __name__ == '__main__':

        setupstr="""
    import scipy, numpy, math
    from utils import factorial
    n = 100
    """

        method1="""
    factorial(n)
    """

        method2="""
    scipy.math.factorial(n)  # same algo as numpy.math.factorial, math.factorial
    """

        nl = 1000
        t1 = Timer(method1, setupstr).timeit(nl)
        t2 = Timer(method2, setupstr).timeit(nl)

        print 'method1', t1
        print 'method2', t2

        print factorial(n)
        print scipy.math.factorial(n)

Which provides:

method1 0.0195569992065
method2 0.00638914108276

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000


Process finished with exit code 0

Upvotes: 1

Related Questions