This isn’t anything out of this world, but it showcases Julia’s ability to represent expressions and to easily perform arbitrary precision arithmetic with GMP/MPFR.
Continued fractions:
function contfrac(x::Real, n::Integer)
n < 1 && return Int[]
fpart, ipart = modf(x)
fpart == 0 ? [Int(ipart)] : [Int(ipart); contfrac(1/fpart, n-1)]
end
foldr((x, y) -> :($x + 1 / $y), contfrac(big(π), 25)) |> println
# 3 + 1 / (7 + 1 / (15 + 1 / (1 + 1 / (292 + 1 / (1 + 1 / (1 + 1 / (1 + 1 / (2 + 1 / (1 + 1 / (3 + 1 / (1 + 1 / (14 + 1 / (3 + 1 / (3 + 1 / (23 + 1 / (1 + 1 / (1 + 1 / (7 + 1 / (4 + 1 / (35 + 1 / (1 + 1 / (1 + 1 / (1 + 1 / 2)))))))))))))))))))))))
foldr((x, y) -> x + 1 // big(y), contfrac(big(π), 75))
# 13926567982265799805873939967043853503//4432964269365850039583559427823398144
If you put the resulting string
foldr((x,y) -> "$x+\\frac1{$y}", contfrac(big(π), 15)) |> println
# 3+\frac1{7+\frac1{15+...}}
in a LaTeX cell you get
3+\frac1{7+\frac1{15+\frac1{1+\frac1{292+\frac1{1+\frac1{1+\frac1{1+\frac1{2+\frac1{1+\frac1{3+\frac1{1+\frac1{14+\frac1{2+\frac1{1}}}}}}}}}}}}}}
Addendum
Of course in general an iterative implementation such as
function contfrac(x::Real, n::Integer)
cf = Int[]
for _ in 1:n
fpart, ipart = modf(x)
push!(cf, Int(ipart))
x = 1 / fpart
end
cf
end
would be preferred, because it reduces allocations and avoids stack overflows. This was however a bit too long for the seven lines restriction. Notice that in the case of continued fractions, to actually overflow the stack while performing meaningful computations requires working with a quite large precision. The default precision 256 of BigFloat
allows to correctly compute only the first 76 terms of the continued fraction of π
.