RosettaCodeData/Task/Continued-fraction/Ruby/continued-fraction.rb

48 lines
1.2 KiB
Ruby

require 'bigdecimal'
# square root of 2
sqrt2 = Object.new
def sqrt2.a(n); n == 1 ? 1 : 2; end
def sqrt2.b(n); 1; end
# Napier's constant
napier = Object.new
def napier.a(n); n == 1 ? 2 : n - 1; end
def napier.b(n); n == 1 ? 1 : n - 1; end
pi = Object.new
def pi.a(n); n == 1 ? 3 : 6; end
def pi.b(n); (2*n - 1)**2; end
# Estimates the value of a continued fraction _cfrac_, to _prec_
# decimal digits of precision. Returns a BigDecimal. _cfrac_ must
# respond to _cfrac.a(n)_ and _cfrac.b(n)_ for integer _n_ >= 1.
def estimate(cfrac, prec)
last_result = nil
terms = prec
loop do
# Estimate continued fraction for _n_ from 1 to _terms_.
result = cfrac.a(terms)
(terms - 1).downto(1) do |n|
a = BigDecimal cfrac.a(n)
b = BigDecimal cfrac.b(n)
digits = [b.div(result, 1).exponent + prec, 1].max
result = a + b.div(result, digits)
end
result = result.round(prec)
if result == last_result
return result
else
# Double _terms_ and try again.
last_result = result
terms *= 2
end
end
end
puts estimate(sqrt2, 50).to_s('F')
puts estimate(napier, 50).to_s('F')
puts estimate(pi, 10).to_s('F')