Estimating e in Python

A while ago I wrote a post on estimating Pi using a variety of methods. As a sort of follow-up I will now write a post on estimating e, or Euler's Number, in Python.

I won't try to summarize what e is or what it is used for as Wikipedia has a comprehensive article on the subject. However, I will include a portrait of Leonhard Euler just after he had washed his hair and changed into his pyjamas.

Swiss mathematician Leonhard Euler
15 April 1707 to 18 September 1783

Let's dive straight into the code which lives in a single file called e.py. (At least you can't accuse me of using overly long filenames). You can download the source code as a zip or clone/download the Github repository.

Source Code Links

ZIP File
GitHub

This is the first part of the source code.

e.py (part 1)

import math

E15DP = "2.718281828459045"

RED = "\x1B[31;1m"
GREEN = "\x1B[32;1m"
WHITE = "\x1B[37;1m"
RESET = "\x1B[0m"


def main():

    print("-----------------")
    print("| codedrome.com |")
    print("| Estimatinge   |")
    print("-----------------\n")

    expansion_1()

    #expansion_2()

    #newtons_series()

    #brothers_formula()


def print_as_text(e):

    """
    Takes a value for e and prints it below a definitive value,
    with matching digits in green and non-matching digits in red
    """


    e_string = "{:1.15f}".format(e)

    print("Definitive: " + WHITE + E15DP + RESET)

    print("Estimated:  ", end="")

    for i in range(0, len(e_string)):
        if e_string[i] == E15DP[i]:
            print(GREEN + e_string[i] + RESET, end="")
        else:
            print(RED + e_string[i] + RESET, end="")

    print("\n")

Near the top of the file I have defined a variable called E15DP which is a string containing e to 15 decimal places. This will be used as a definitive value to compare with values we calculate. The name is all upper case to denote that it should be considered as a constant.

Next we have a few colour constants to output text to the console in various colours.

The main function consists of four function calls to estimate e using various methods. All but the first are commented out for now as we'll run them one at a time.

The print_as_text function takes a value for e and converts it to a string with 15 decimal places. It then prints it after the definitive value, with correct digits in green and incorrect ones in red.

e.py (part 2)

def expansion_1():

    print(WHITE + "First expansion\nn = 100000\n---------------" + RESET)

    n = 100000
    e = (1 + 1/n)**n

    print_as_text(e)

The first function to calculate e is expansion_1 which implements this formula...

First Expansion

e = (1 + 1/n)n

...with a value of n = 100000

We now have enough to run with this command.

Running the program

python3.7 e.py

The output is

Program Output

-----------------
| codedrome.com |
| Estimating e  |
-----------------

First expansion
n = 100000
---------------

Definitive: 2.718281828459045
Estimated:  2.718268237192297

As you can see this gives us 4dp of accuracy; you might like to experiment with different values of n. Now let's try another expansion to implement this formula with n = 0.000000001.

Second Expansion

e = (1 + n)1/n

e.py (part 3)

def expansion_2():

    print(WHITE +
          "Second expansion\nn = 0.000000001\n----------------" +
          RESET)

    n = 0.000000001
    e = (1 + n)**(1/n)

    print_as_text(e)

Comment out expansion_1() in main, uncomment expansion_2() and run the program again. This is the output.

Program Output

-----------------
| codedrome.com |
| Estimating e  |
-----------------

Second expansion
n = 0.000000001
----------------

Definitive: 2.718281828459045
Estimated:  2.718282052011560

This gives us 5dp of accuracy but again you can try different values of n.

Now let's move on to the third method, Newton's Series, for which the formula is:

This means we start off with n = 0, set e to 1/n!, increment n and then keep adding 1/n! to e for as long as we want.

(n! means the product of all integers up to and including n, for example 4! = 4 x 3 x 2 x 1 = 24. Incidentally 0! = 1.)

e.py (part 4)

def newtons_series():

    print(WHITE + "Newton's Series\nn = 0 to 12\n---------------" + RESET)

    e = 0

    for n in range(0, 13):
        e += (1 / math.factorial(n))

    print_as_text(e)

Uncomment newtons_series() in main and run the program.

Program Output

-----------------
| codedrome.com |
| Estimating e  |
-----------------

Newton's Series
n = 0 to 12
---------------

Definitive: 2.718281828459045
Estimated:  2.718281828286169

Sir Isaac gives us 9dp of accurancy with a maximum value of n = 13.

As with π people are still working on ways to calculate e and I'll finish off with this impressive recently discovered method, Brothers Formula, devised as recently as 2004.

As with Newton's Series this is the sum of a infinite series although rather more complex.

e.py (part 5)

def brothers_formula():

    print(WHITE + "Brothers Formula\nn = 0 to 8\n----------------" + RESET)

    e = 0

    for n in range(0, 9):
        e += (2*n + 2) / (math.factorial(2*n + 1))

    print_as_text(e)

The extra complexity pays off though: we only need to count to 8 to get 15dp (possibly more) of accuracy.

Program Output

-----------------
| codedrome.com |
| Estimating e  |
-----------------

Brothers Formula
n = 0 to 8
----------------

Definitive: 2.718281828459045
Estimated:  2.718281828459045