Processing math: 100%

© 2018 Suzy Beeler. This work is licensed under a Creative Commons Attribution License CC-BY 4.0. All code contained herein is licensed under an MIT license

This exercise was generated from a Jupyter notebook. You can download the notebook here.


Objective

This tutorial will illustrate the concept of Taylor series expansion, where a given function can be approximated with a polynomial function. We will see that increasing the order of the polynomial results in ever better approximations.

In [1]:
# import the necessary modules
import numpy as np
import matplotlib.pyplot as plt

# allows us to compute factorials 
import math

# For pretty plots
import seaborn as sns
rc={'lines.linewidth': 2, 'axes.labelsize': 14, 'axes.titlesize': 14, \
    'xtick.labelsize' : 14, 'ytick.labelsize' : 14}
sns.set(rc=rc)

Taylor series expansion of ex

The Taylor series expansion of ex is given by

ex=1 + x+ x22! + x33! + x44! + . . . + xnn!.

We see that each new term in this series takes on the form of xnn!. This means we can iteratively determine the Taylor series expansion for an increasing number of terms. That is, we can use the 0th order approximation to get the 1st order approximation, and we can use the 1st order approximation to get the 2nd order approximation, and so on. To do this, we can store our y values in a 2D array, where the rows correspond to the order of the polynomial we are using and the columns correspond to increasing values of x for which we are computing.

In [2]:
# max number of terms we want to expand to
n_terms = 5

# range of x values to look at
x_vals = np.linspace(0,2,100)

# intialize the array of  y_vals
y_vals = np.zeros([n_terms,len(x_vals)])

# loop through the number of terms
for n in range(n_terms):
    
    # special case for 0th order
    if n == 0:
        y_vals[n,:] = np.ones(len(x_vals))
      
    # otherwise nth order is n-1th order plus new term
    else:
        new_term = x_vals**n / math.factorial(n)
        y_vals[n,:] = y_vals[n-1,:] + new_term

We can now loop through our y values array to plot our approximations for an increasing number of terms. We can also plot the real function, ex, for comparison.

In [3]:
# loop through number of terms and plot
for n in range(n_terms):
    label = str(n) + " order"
    plt.plot(x_vals,y_vals[n,:], label=label)
    
# plot the real function  
plt.plot(x_vals, np.exp(x_vals), label="$e^x$")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
Out[3]:
<matplotlib.legend.Legend at 0x1a1cff07b8>

Nice! We see how increasing the order of our polynomial brings us ever closer to the true form of the ex function. Using this code a template, we can now compute the Taylor series expansion for a number of different functions. The only things we may need to change are the 0th order term and the form of each new term.

Taylor series expansion of cos(x)

The Taylor series expansion of cos(x) is given by

cos(x)=1  x22! + x44!  x66! + x88!  . . . + (1)nx2n(2n)!.

In [4]:
# max number of terms we want to expand to
n_terms = 5

# range of x values to look at
x_vals = np.linspace(0,2*np.pi,100)

# intialize the y_vals
y_vals = np.zeros([n_terms,len(x_vals)])

# loop through the number of terms
for n in range(n_terms):
    
    # special case for 0th order
    if n == 0:
        y_vals[n,:] = np.ones(len(x_vals))
      
    # otherwise nth order is n-1th order plus new term
    else:
        new_term = (-1)**n * x_vals**(2*n) / math.factorial(2*n)
        y_vals[n,:] = y_vals[n-1,:] + new_term
In [5]:
# loop through number of terms and plot
for n in range(n_terms):
    label = str(n) + " order"
    plt.plot(x_vals,y_vals[n,:], label=label)

# plot the real function    
plt.plot(x_vals, np.cos(x_vals), label="$cos(x)$")
plt.xlabel("x")
plt.ylabel("y")
plt.ylim([-1.1,1.1]) # set y-axis to make it easier to see
plt.legend()
Out[5]:
<matplotlib.legend.Legend at 0x1a1d96cf60>

Taylor series expansion of ln(1+x)

The Taylor series expansion of ln(1+x) is given by

ln(1+x)=x  x22 + x33  x44 + x55  . . . + (1)nxn+1n+1.

In [6]:
# max number of terms we want to expand to
n_terms = 5

# range of x values to look at
x_vals = np.linspace(0,1,100)

# intialize the y_vals
y_vals = np.zeros([n_terms,len(x_vals)])

# loop through the number of terms
for n in range(n_terms):
    
    # special case for 0th order
    if n == 0:
        y_vals[n,:] = x_vals
      
    # otherwise nth order is n-1th order plus new term
    else:
        new_term = (-1)**n * x_vals**(n+1) / (n+1)
        y_vals[n,:] = y_vals[n-1,:] + new_term
In [7]:
# loop through number of terms and plot
for n in range(n_terms):
    label = str(n) + " order"
    plt.plot(x_vals,y_vals[n,:], label=label)

# plot the real function 
plt.plot(x_vals, np.log(1 + x_vals), label="$ln(1+x)$")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
Out[7]:
<matplotlib.legend.Legend at 0x1a1ddfb3c8>

Taylor series expansion of 11+x

The Taylor series expansion of 11+x is given by

11+x = 1  x + x2  x3 + x4  . . . + (1)nxn.

In [8]:
# max number of terms we want to expand to
n_terms = 5

# range of x values to look at
x_vals = np.linspace(0,1,100)

# intialize the y_vals
y_vals = np.zeros([n_terms,len(x_vals)])

# loop through the number of terms
for n in range(n_terms):
    
    # special case for 0th order
    if n == 0:
        y_vals[n,:] = np.ones(len(x_vals))
      
    # otherwise nth order is n-1th order plus new term
    else:
        new_term = (-1)**n * (x_vals**n)
        y_vals[n,:] = y_vals[n-1,:] + new_term
In [9]:
# loop through number of terms and plot
for n in range(n_terms):
    label = str(n) + " order"
    plt.plot(x_vals,y_vals[n,:], label=label)

# plot the real function    
plt.plot(x_vals, 1/(1+x_vals), label="$1/(1+x)$")
plt.xlabel("x")
plt.ylabel("y")
plt.ylim([0,1.1])
plt.legend()
Out[9]:
<matplotlib.legend.Legend at 0x1a1deeccf8>