Factorial in numpy and scipy

PythonNumpyScipy

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

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.

Solution 3 - Python

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)

Solution 4 - Python

    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))

Solution 5 - Python

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

Solution 6 - Python

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMOONView Question on Stackoverflow
Solution 1 - PythonAshwini ChaudharyView Answer on Stackoverflow
Solution 2 - PythonYuxiang WangView Answer on Stackoverflow
Solution 3 - PythonJanne KarilaView Answer on Stackoverflow
Solution 4 - PythonStefan GruenwaldView Answer on Stackoverflow
Solution 5 - Pythonsudheer naiduView Answer on Stackoverflow
Solution 6 - PythonSeFView Answer on Stackoverflow