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
exp(x)
is implemented at a much lower level than e**x
. It is essentially a wrapper for a function in libc. Said function is probably (at some level) using the Taylor series expansion to calculate the value directly (or possibly some other mathematical method, I'm not sure).
On the other hand, e**x
is taking a number and raising it to a power. This is an entirely different strategy, and probably less precise in most circumstances. Raising numbers to powers is difficult to do precisely.
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 C pow
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:
2.718281828459045 09079559829...
Whereas the real value of e is
2.718281828459045 23536028747...
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 using exp
due to the details of the algorithms it uses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With