Numpy Exercise 2

Imports


In [1]:
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

Factorial

Write a function that computes the factorial of small numbers using np.arange and np.cumprod.


In [2]:
def np_fact(n):
    """Compute n! = n*(n-1)*...*1 using Numpy."""
    if n == 0:
        return 1
    else:
        c = np.arange(1, n+1, 1)
        return c.cumprod()[n-1]

In [3]:
assert np_fact(0)==1
assert np_fact(1)==1
assert np_fact(10)==3628800
assert [np_fact(i) for i in range(0,11)]==[1,1,2,6,24,120,720,5040,40320,362880,3628800]

Write a function that computes the factorial of small numbers using a Python loop.


In [4]:
def loop_fact(n):
    result = 1
    """Compute n! using a Python for loop."""
    if n == 0:
        return 1
    else:
        while n > 0:
            result = result*n
            n-=1
    return result

In [5]:
assert loop_fact(0)==1
assert loop_fact(1)==1
assert loop_fact(10)==3628800
assert [loop_fact(i) for i in range(0,11)]==[1,1,2,6,24,120,720,5040,40320,362880,3628800]

Use the %timeit magic to time both versions of this function for an argument of 50. The syntax for %timeit is:

%timeit -n1 -r1 function_to_time()

In [6]:
print("Argument of 50")
%timeit -n1 -r1 np_fact(50)
%timeit -n1 -r1 loop_fact(50)

print("Argument of 90000")
%timeit -n1 -r1 np_fact(90000)
%timeit -n1 -r1 loop_fact(90000)


Argument of 50
1 loops, best of 1: 49.1 µs per loop
1 loops, best of 1: 29.1 µs per loop
Argument of 90000
1 loops, best of 1: 1.96 ms per loop
1 loops, best of 1: 3.75 s per loop

In the cell below, summarize your timing tests. Which version is faster? Why do you think that version is faster?

Loop_fact is faster than np_fact for small values. I believe this is because np_fact is creating an array and every entry in the array, while loop_fact is only directly doing the computation. But you can notice that as the argument is increased to very large values np_fact is much faster.