While programming I noticed a difference between the result of math.exp(2) and math.e**2. As you can see below, this difference does not arise when calculating e^1.
Not being an experienced programmer, I wondered why this differs?
I assume it has something to do with rounding up. The python docs say that math.exp(x)
return e**x
, but this appears not to be precisely correct. So how come that the math.exp(x)
operation differs from math.e**x
?
>>> math.exp(1)
2.718281828459045
>>> math.e**1
2.718281828459045
>>> math.exp(1)==math.e**1
True
>>> math.exp(2)
7.38905609893065
>>> math.e**2
7.3890560989306495
>>> math.exp(2)==math.e**2
False
>>> math.exp(100)
2.6881171418161356e+43
>>> math.e**100
2.6881171418161212e+43
>>> math.exp(100)==math.e**100
False
It's different due to differences in the implementation of the functions. Neither one is perfect due to the nature of floating point.
The
**
operator is implemented in floatobject.c and contains a lot of special cases, but none of them are invoked here, so it ultimately reaches the standard Cpow
function. The math.pow function ultimately does the same thing.The
exp
function is a straightforward wrapper around the C function of the same name, defined with a macro in mathmodule.c.As it happens, exp is more precise (both of the results match, to within the precision allowed by floating point, high-precision answers I calculated in bc). Most likely it is because internally to pow, it is calculating the extended-precision logarithm of the double-precision
e
value you pass as the first argument, which is slightly smaller than 1.The fundamental issue is that
math.e
, which is the number you're calculating the power of, is:Whereas the real value of e is
And this error is compounded when you use
pow
or**
, whereas it may not be (or may be using a higher precision value internally) if you're usingexp
due to the details of the algorithms it uses.