Download or view e.frink in plain text format
/** Program to calculate e to arbitrary precision. This uses binary
splitting for speed.
You usually use this by calling E.getE[digits] which will return e
to the number of digits you specify.
This version has been updated to be fastest with
Frink: The Next Generation. Due to limitations in Java's BigDecimal
class, this is limited to a little over 101 million digits.
This differs from the basic algorithm in eBinarySplitting.frink
because when you ask for more digits of e than you previously had,
this *resumes* the calculation rather than starting from scratch.
See:
http://numbers.computation.free.fr/Constants/Algorithms/splitting.html
http://www.ginac.de/CLN/binsplit.pdf
*/
class E
{
class var largestDigits = -1
class var cacheE = undef
/** These variables help us resume the state of the binary-splitting
algorithm. */
class var largestP = 1
class var largestQ = 1
class var largestK = 1
class var logFactorial = 0.
/** This is the main public method to get the value of e to a certain
number of digits, calculating it if need be. If e has already been
calculated to a sufficient number of digits, this returns it from the
cache.
*/
class getE[digits = getPrecision[]] :=
{
origPrec = getPrecision[]
try
{
setPrecision[digits]
if (largestDigits >= digits)
return 1. * cacheE
else
return 1. * calcE[digits]
}
finally
setPrecision[origPrec]
}
/** This is an internal method that calculates the digits of e if
necessary. */
class calcE[digits] :=
{
origPrec = getPrecision[]
try
{
setPrecision[15]
// Find number of terms to calculate.
// ln[x!] = ln[1] + ln[2] + ... + ln[x]
logMax = digits * ln[10]
k = largestK
while (logFactorial < logMax)
{
logFactorial = logFactorial + ln[k]
k = k + 1
}
setPrecision[digits+3]
if largestK < k // We may have already calculated enough!
{
if (largestK == 1) // This is the first iteration
{
p = P[0,k]
q = Q[0,k]
} else
{
// Continuing iterations
pmb = P[largestK, k]
qmb = Q[largestK, k]
p = largestP qmb + pmb
q = largestQ qmb
}
// Store the biggest values back in the cache
largestP = p
largestQ = q
largestK = k
cacheE = 1 + (1. * p)/q
}
setPrecision[digits]
return 1. * cacheE
}
finally
setPrecision[origPrec]
}
/** Private method for binary splitting. */
class P[a,b] :=
{
if (b-a) == 1
return 1
m = (a+b) div 2
r = P[a,m] Q[m,b] + P[m,b]
return r
}
/** Private method for binary splitting. */
class Q[a,b] :=
{
if (b-a) == 1
return b
m = (a+b) div 2
return Q[a,m] Q[m,b]
}
}
Download or view e.frink in plain text format
This is a program written in the programming language Frink.
For more information, view the Frink
Documentation or see More Sample Frink Programs.
Alan Eliasen was born 20217 days, 15 hours, 8 minutes ago.