TP: Implementing the Exponential Function (4/5)#
Attention
This exercise is marked with a ♣ and is therefore of a more advanced level; do not hesitate to skip it if it seems difficult to you in order to not waste too much time, and to come back to it later.
Part 4: Calculating the exponential with a fixed relative precision ♣#
In Part 2, you implemented an expRang
function that calculates an approximation
of the exponential by truncating the sum at a certain rank decided in advance. However,
the rank required to obtain good precision depends on the real number \(x\) for which
we want to calculate \(e^x\). We now seek to calculate an approximation of
the exponential by fixing the precision and no longer the rank. To do this, we will write a
new function to approximate the exponential, in which the rank at which we
stop the sum will not be decided in advance, but will depend on the evolution of the calculation
that we are doing.
Begin by copying and pasting your puissance
and factorielle
functions from part 1 and egal
from
part 3 into the following four cells:
### BEGIN SOLUTION
def puissance( x, n):
r = 1
for i in range(n):
r *= x
return r
### END SOLUTION
### BEGIN SOLUTION
def factorielle(n):
r = 1
for i in range(1, n+1):
r *= i
return r
### END SOLUTION
### BEGIN SOLUTION
def egal(x, y, epsilon):
v = abs(x-y)
return ((v < epsilon * abs(x)) and (v < epsilon * abs(y)))
### END SOLUTION
Implement a new exponential approximation function that sums the terms
\(\frac{x^i}{i!}\) until the next term to be added does not change the value of
the sum, according to the given precision:
def expPrecision(x, epsilon):
""" Calcul de la fonction exponentielle à precision fixée
* Parametre x : un nombre flottant
* Parametre epsilon un nombre flottant
* Retourne e^x avec précision epsilon
"""
### BEGIN SOLUTION
e1 = 0
e2 = 1
i = 1
while(not egal(e1,e2,epsilon)):
e1 = e2
e2 += puissance(x,i) / factorielle(i)
i += 1
return e2
### END SOLUTION
epsilon = 0.000000001
epsilon = 1e-9
The following calculation should return \(2.718 281 828...\):
expPrecision(1, epsilon)
2.7182818282861687
There are not necessarily enough significant figures displayed to verify this.
Instead, let’s do a test:
assert( abs( expPrecision(1, epsilon) - 2.718281828459 ) < epsilon )
Our stopping test does not actually guarantee obtaining an epsilon precision: even if
the next term is smaller than epsilon, the accumulation of all the following terms
could largely exceed epsilon, as in the following examples:
assert( abs(expPrecision(3, epsilon) - 20.085536923 ) < 5*epsilon )
assert( abs( expPrecision(5, epsilon) - 148.413159102 ) < 50*epsilon )
Compare your results with the exp
function in Python:
import math
math.exp(5)
148.4131591025766
math.exp(3)
20.085536923187668
Review of Part 4#
Very good, you have implemented the calculation of the exponential function with fixed precision.
Now let’s study its performance by calculating its execution time:
import time
start = time.time()
expPrecision(10, 0.00000001)
print(time.time() - start)
0.000164031982421875
In part 5, you will attempt to optimize this implementation.