48 lines
1.2 KiB
Ruby
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')
|