#!/usr/bin/env python
# coding: utf-8

# In[1]:


#example from slides where overflow can be avoided by an alternative computation method
def myf1(n):
    from math import factorial
    return n**n / factorial(n)


# In[7]:


myf1(200.)


# In[15]:


def myf2(n):
    y = 1
    for i in range(int(n)):
        y = y * (n / (n-i))
    return y


# In[16]:


myf2(200.)


# In[12]:


int(200.)


# In[19]:


#add up terms in the Taylor series of sin(x) about 0
def sin_taylor(x, n):
    from math import factorial
    y = 0
    d = 1
    s = 1
    while (d <= n):
        y = y + s*x**d / factorial(d)
        d = d + 2
        s = -s
    return y


# In[25]:


from numpy import pi


# In[31]:


sin(10*pi)


# In[38]:


sin_taylor(10*pi, 110) #should be zero, if not for roundoff error


# In[ ]:





# In[24]:


from numpy import sin
sin(0.1)


# In[40]:


def myexp(x):
    from numpy import sqrt
    return sqrt(x + 1) - 1


# In[42]:


myexp(1E-16)


# In[43]:


def myexp2(x): #has less roundoff error than the alternative form
               #for x close to 0
    from numpy import sqrt
    return x / (sqrt(x + 1) + 1)


# In[45]:


myexp2(1E-16)


# In[48]:


#add up terms in the Taylor series of exp(x) about 0
def exp_taylor(x, n):
    from math import factorial
    y = 0
    d = 0
    while (d <= n):
        y = y + x**d / factorial(d)
        d = d + 1
    return y


# In[49]:


exp_taylor(1, 100)


# In[50]:


from numpy import exp
exp(1)


# In[52]:


y = exp(-7)
print(y)


# In[51]:


y1 = exp_taylor(-7, 50)
print(y1)


# In[53]:


#fractional error
abs(y1 - y) / abs(y)


# In[54]:


y2 = 1 / exp_taylor(7, 50)
print(y2)


# In[55]:


abs(y2 - y) / abs(y)


# In[62]:


#error in centered finite difference approximation to derivative
from numpy import logspace, sin, cos
h = logspace(-10, 0, 100)
f = lambda x: sin(x)
x = 1
dt = cos(x)
d = (f(x + h) - f(x - h)) / (2*h)
ef = abs(d - dt) / abs(dt) #fractional errors relative to the analytic derivative


# In[64]:


from matplotlib.pyplot import loglog, xlabel, ylabel

loglog(h, ef)
xlabel('step size h')
ylabel('fractional error of finite difference derivative estimate')


# In[61]:


(f(x + 0.01) - f(x - 0.01)) / (2*0.01)


# In[60]:


dt


# In[ ]:




