Difference between math.exp(2) and math.e**2

11.3k views Asked by At

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
2

There are 2 answers

4
Random832 On BEST ANSWER

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.

0
Kevin On

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.