Approximating eˣ using a Taylor series and eval
Introduction
In this article we calculate the value of eˣ (x=5 in this example). It’s not efficient and you shouldn’t be constructing elementary functions in eval, but it does illustrate a few interesting features of the module: The use of utf-8 variable names, nested for loops, and printf.
First, let’s give you the entire Gravwell query. We’ll break down each section from there. The query doesn’t require any data, but we need at least one entry to invoke eval, so we simply grab one from the gravwell tag.
tag=gravwell limit 1
| eval
// Taylor series of eˣ is ∑xⁿ/n! from 0 to ∞
x = 5.0; // exponent
ex = 0.0; // starting value
// for loop expresses the series summation
for (i = 0; i < 20; i++) {
// xⁿ (dividend)
dividend = math_pow(x,i);
// n! (divisor)
if (i == 0 || i == 1) {
divisor = 1;
} else {
divisor = 1;
for (j = 2; j <= i; j++) {
divisor = divisor * j;
}
}
// quotient
xn = dividend/divisor;
// add to the running sum
ex = ex + xn;
}
| eval result = printf("e⁵ == %.5f", ex);
| table result
Setup
tag=gravwell limit 1
This simply kicks off a query with a single entry. Eval won’t run without an entry. We don’t use the data.
Initial conditions
| eval
// Taylor series of eˣ is ∑xⁿ/n! from 0 to ∞
x = 5.0; // exponent
ex = 0.0; // starting value
We set our x (the exponent) to 5. We could use any number here. We can’t calculate this number to more than about 4 decimal places using this approach (more on that next), but it’s worth noting that according to Wolfram alpha:
e⁵ = 148.413159102576603421115580040552279623487667593878989046 ≈ 148.4131
We also set the initial value of our (eventual) output, ex. While eval does support utf-8 throughout, it doesn’t support superscript or diacritics, so we just say “ex” here.
The main loop
The Taylor series definition of eˣ is ∑xⁿ/n!, from 0 to ∞. The main loop of our example implements the series summation.
// for loop expresses the series summation
for (i = 0; i < 20; i++) {
Why do we only iterate 20 times? This is because, looking ahead, we know we have to calculate n factorial (n!), and we also know that the largest factorial we can fit in an int64 (the width of an eval integer) is 20!. To that end, we stop after 20 iterations and take whatever result we have.
It’s also worth noting that while the Taylor series uses n, we use the canonical loop variable i instead.
Dividend
// xⁿ (dividend)
dividend = math_pow(x,i);
This one is easy, simply calculate xⁿ using eval’s built-in power function.
Divisor
// n! (divisor)
if (i == 0 || i == 1) {
divisor = 1;
} else {
divisor = 1;
for (j = 2; j <= i; j++) {
divisor = divisor * j;
}
}
Now things start getting interesting. eval doesn’t have a built-in factorial function, so we need to calculate it ourselves. We do this with another for loop (and some edge cases to cover the definition of factorial at n=0 and n=1).
A major thing to note here: eval doesn’t have any notion of scope.
divisoris first declared inside the if and for statements, but the value can be used throughout the program after the first declaration. Keep this in mind.
Sum it up
// quotient
xn = dividend/divisor;
// add to the running sum
ex = ex + xn;
}
More simple stuff, just calculate the quotient and add it to our running sum ex.
Printing
| eval result = printf("e⁵ == %.5f", ex);
| table result
Finally, we print our result using another eval module invocation, and specify we only want our result printed to 5 decimal places.
e⁵ == 148.4131
Success!
