// Generate a continued fraction (as an array) for the number x.// No more than "limit" terms will be produced.//// As part of this process, we build up the represented value (the// "convergent") as we go to determine if we've exceeded the available// working precision.
continuedFraction[x, limit=10] :=
{
r = x
result = new array
count = 0
a = floor[r]
var p
var q
p2 = 1
q2 = 0
p1 = a
q1 = 1

// Turns an array indicating a continued fraction into a single// fraction (or array of fractions) indicating its value.// This performs the calculation top-down.//// Since the result for a canonical continued fraction will always be an// exact rational number, it is safe to do the calculation top-down or// bottom-up.//// if asArray is true, this will return the results as an array of successive// approximations to the value (also called convergents of the continued// fraction.)
continuedFractionToFraction[a, asArray=false] :=
{// n is the order of the continued fraction (the index of the last element,// starting with 0)
n = length[a] - 1

if n == 0
return a@0

if asArray == true
results = new array

// The final value will be p/q. For canonical continued fractions, p and q// will both always be integers.//// An interesting note is that p/q is *already* always in simplest form,// that is, the fraction will never need reducing. Or, in other terms,// gcd[p,q] = 1, or in even other terms, p and q share no common factors.
var p
var q

/** This is a "bottom-up" calculation of a continued fraction, turning it into
a fraction. It's more obvious than the above "top-down" calculation, but
this approach doesn't work with infinite continued fractions, and doesn't
show the convergence of continued fractions. (All canonical integer-valued
continued fractions will converge, see Khinchin, theorem 10)

Since for canonical continued fractions the result is an exact rational
number, calculations can be done "top-down" or "bottom-up" without loss of
accuracy. This version is preserved for obviousness and clarity.
**//*
continuedFractionToFraction[a] :=
{
n = length[a] - 1

frac = 0
for i = n to 1 step -1
frac = 1/(a@i+frac)

return a@0 + frac
}
*/

// Returns the closest fraction to x as a fraction by creating a continued// fraction with no more than "limit" terms.
closestFraction[x, limit=10] :=
{
cf = continuedFraction[x,limit]
return continuedFractionToFraction[cf]
}

// Turns an array representing a continued fraction back into an array// of fractions. Each fraction in the array shows the results of using more// and more terms from the continued fraction representation.
continuedFractionToArray[cf] :=
{
continuedFractionToFraction[cf, true]
}

// Return an array which is a series of fractions representing// successively-better approximations to the number x. No more than "limit"// terms will be produced.
approximations[x, limit=10] := continuedFractionToArray[continuedFraction[x,limit]]

// Return an array which is a series of fractions representing// successively-better approximations to the number x. No more than "limit"// terms will be produced.
approximationsWithErrors[x, limit=10] :=
{
result = new array
approximations = continuedFractionToArray[continuedFraction[x,limit]]
for a = approximations
result.push[ [a, (a-x)/x] ]