Calculating ℯ to high precision in a web browser

Written by Guy Fernando

Created Jan 2023 - Last modified Sep 2024

The number ℯ, also known as Euler's Number
refers to a mathematical expression for the base of the natural logarithm, and is an important constant number in mathematics.
It is a transcendental number, meaning that it is not the root of a non-zero polynomial with finite degree with rational
coefficients. The value of ℯ quoted to ten decimal places is approximately 2.7182818284.

An exponential function can be mathematically expressed in the form y = a^{x}, where ‘x’ is the independent variable, ‘y’
the dependent variable, and ‘a’ is a constant known as the base of the function. The value of ‘a’ determines the exponential
growth, the larger the value of ‘a’ the higher the rate of exponential growth. Many examples of this kind of growth are
experienced in nature, physics, and economics.

There is a single special case for ‘a’, when the derivative or slope of the growth curve is the same as its value, similarly
the integral or area under the growth curve is also the same as its value. The special case is when ‘a’ is equal to the
constant ℯ.

\( \begin{aligned}
\frac{d}{dx} e^{x} = e^{x}
\end{aligned} \)

\( \begin{aligned}
\int e^{x} dx = e^{x} + C
\end{aligned} \)

Knowing this property greatly simplifies the work involved when solving calculus.

Try changing the value of the 'a' coefficient towards the value of ℯ to see all the curves below converge.
Notice that derivative(a^{x}) and integral(a^{x}) are only equal to a^{x} when a = 2.72 (i.e. when ≈ ℯ).

In 1683 Jacob Bernoulli discovered the ℯ
constant while studying compound interest when payments of interest ‘n’ occur more frequently. The expression below approaches
ℯ as the limit approaches infinity:

\( \begin{aligned}
e = \lim_{n \rightarrow \infty } \big(1 + \frac{1}{k} \big)^{k}
\end{aligned} \)

Leonhard Euler extended and formalized the work of
Bernoulli as well as other areas in mathematics. In 1748 he published ideas of ℯ in his two volume book entitled
Introductio in analysin infinitorum,
where he described the logarithm to base ℯ as the natural or hyperbolic logarithm, and gave this infinite series:

\( \begin{aligned}
e^{x} = \sum_{k=0}^\infty \frac{ x^{k} }{k!} = \frac{1}{0!} +\frac{x}{1!} + \frac{ x^{2} }{2!} + \frac{ x^{3} }{3!} + ...
\end{aligned} \)

By setting x = 1 we get an expression for evaluating ℯ:

\( \begin{aligned}
e = \sum_{k=0}^\infty \frac{1}{k!} = \frac{1}{0!} +\frac{1}{1!} + \frac{1}{2!} + \frac{1}{3!} + ...
\end{aligned} \)

The online ℯ calculator described next uses this infinite series as an algorithm for calculating ℯ to a high precision.

The online ℯ calculator presented here is able to evaluate ℯ up to one million decimal places the previously described
infinite series algorithm. Bear in mind the more digits selected, the longer the calculation will take to complete. Be prepared
to wait around sometime when calculating ℯ to more than 1000 digits, though this will depend on the speed of your computer,
and the algorithm chosen. When the calculation completes, the result will be displayed below.

Select the number of digits to calculate, and then click the Calculate button.

The process of evaluating ℯ when using an infinite series involves a repetition of calculations, the more repetitions
we use the better the approximation. Whether performing these calculations by hand or using a digital computer, it is obviously
advantageous to arrive upon an answer with the fewest of repetitions. Some infinite series equations converge faster
than others, which is another way of saying that the value is arrived upon more quickly for a given amount of repetitions
or iterations.

The Euler number ℯ can be represented as an infinite series.

\( \begin{aligned}
e = \sum_{k=0}^ \infty \frac{{1}}{k!}
\end{aligned} \)

\( \begin{aligned}
\hspace{3mm} = 1 + \frac{1}{1} + \frac{1}{1.2} + \frac{1}{1.2.3} + \cdots
\end{aligned} \)

Digits calculated per iteration: 2

Computational complexity:
\( \begin{aligned}
O( k^2 )
\end{aligned} \)

The JavaScript implementation is shown here.

` ````
// Calculating e using the Infinite series.
// Guy Fernando (2023)
Decimal.precision = this.digits + 2;
var euler = new Decimal(0);
var iterations = (this.digits / this.digitsPerIteration);
// Infinite series.
for (var k = 0; k < iterations; k++) {
// Partial summation.
euler = euler.plus(Decimal(1).dividedBy(this.factorial(k)));
}
// Set significant digits.
euler = euler.toSD(this.digits);
```

In computer science, the Big 'O' notation
is used as a basis to quantify computational complexity. The notation applies to algorithms that are repetitive such
as in a software loop construct, k being the number iterations before the loop terminates. The notation is a technique
used to classify an algorithm's running time for a given number of iterations. Since the algorithms presented here all
share the same structure, they too share the same computational complexity classification.

The computation is performed within your web browser using JavaScript. The calculation is executed in a separate web
worker thread to allow this web page to remain responsive and to be scrolled while the calculation is in progress.

To evaluate an approximation of ℯ to high precision, the built-in 64-bit IEEE 754 floating point numerical system that
JavaScript uses cannot be used beyond 15 decimal places. To achieve higher accuracy, an
arbitrary precision numeric
library such as Decimal.js is used. Decimal.js is a self
contained open-source library with a large community of users. It is used to calculate all the algorithms presented in this
article to a precision of up to a million decimal places.

The full javascript code listing is shown here.

` ````
// Guy Fernando (2023).
// Calculates e using various algorithms.
// Implementation using arbitary precision arithmetic library, decimal.js.
importScripts('decimal.min.js');
// Abstract base class for calculating e.
//
class EulerAlgorithm {
// Constructor.
//
constructor(digits, digitsPerIteration) {
this.digits = digits;
this.digitsPerIteration = digitsPerIteration;
this.startTime = 0;
this.endTime = 0;
}
// Factorial that doesn't overflow with large n.
//
factorial(n) {
try {
var i = 2, r = new Decimal(1);
for (; i <= n; r = r.times(i++))
;
}
catch (err) {
console.log(err.message);
}
return r;
}
// Gets the time taken in milliseconds to calculate a single e digit.
//
getTimePerDigit() {
return ((this.endTime - this.startTime) / this.digits).toFixed(2);
}
}
// Infinite Series method for calculating e.
//
class Infinite extends EulerAlgorithm {
// Constructor.
//
constructor(digits) {
// The number of digits, and decimal digits the algorithm generates per iteration.
super(digits, 2);
}
// The Infinite series e calculation.
//
calculate() {
try {
// Journal start time.
this.startTime = performance.now();
Decimal.precision = this.digits + 2;
var euler = new Decimal(0);
var iterations = (this.digits / this.digitsPerIteration);
// Infinite series.
for (var k = 0; k < iterations; k++) {
// Partial summation.
euler = euler.plus(Decimal(1).dividedBy(this.factorial(k)));
}
// Set significant digits.
euler = euler.toSD(this.digits);
// Journal end time.
this.endTime = performance.now();
return euler;
}
catch (err) {
console.log(err.message);
return 0;
}
}
}
// Web worker message receiver.
//
self.onmessage = function (event) {
// Reconstitute json object containing parameters.
var jsonParameters = JSON.parse(event.data);
// Extract parameters.
var digits = Number(jsonParameters.Digits);
var algorithm = jsonParameters.Algorithm;
// Instantiate required algorithm.
// So far the Infinite Series is the only algorithm implemented.
var e;
switch (algorithm) {
case "Infinite Series":
e = new Infinite(digits);
break;
}
// Perform pi calculation.
const eValue = e.calculate();
const timePerDigit = e.getTimePerDigit();
// Send json message containing results to main thread.
var jsonResult = { Algorithm: algorithm, Digits: digits, EValue: eValue.toString(), TimePerDigit: timePerDigit.toString() };
self.postMessage(JSON.stringify(jsonResult));
};
```

The algorithm presented in this article is an infinite series, as a result computational memory requirements and execution
time will be a function of the number of digits that need to be calculated. Furthermore the computer memory requirements
will roughly be proportional to the number of digits required, and the computer execution time per digit will exponentially
increase as the number of digits required increases.

Decimal.js is an excellent small footprint arbitrary-precision library for JavaScript. It lends itself perfectly for evaluating
infinite series algorithms as described in this article.

This website is powered using ultra low power green locally based servers.

Copyright © i4cy 2000-2024. All rights reserved.