在Ruby中递归地替换小数表达式的最后一个分母

时间:2014-08-29 16:11:14

标签: ruby recursion

我想制作一个逐步扩展两个平方根的无限连续分数的函数,即:

sqrt 2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213...

或者更清楚:

WikiPedia

(来自Wikipedia entry which illustrates the solution to quadratic equation x^2 = 2 (or x = sqrt 2) using continued fractions.

前四次迭代等于:

1 + 1/2 = 3/2 = 1.5
1 + 1/(2 + 1/2) = 7/5 = 1.4
1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...
1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...

在Ruby代码中我们得到:

1 + Rational(1, 2)
1 + Rational(1, 2 + Rational(1, 2))
1 + Rational(1, 2 + Rational(1, 2 + Rational(1, 2)))
1 + Rational(1, 2 + Rational(1, 2 + Rational(1, 2 + Rational(1, 2))))

可以看出,在下一次迭代中,最后一个分母(2)被2 + Rational(1, 2)替换。

如何编写可以调用自身并以递归方式打印结果的函数expand

伪代码:

def expand rational
  puts expand rational.replace_last_denominator_with(2 + Rational(1, 2))
end

我遇到的问题是我没有干净的方法来替换最后一部分。我想过将表达式转换为字符串,用表达式替换最后一个数字,然后将其转换回代码。但我相信必须有更好的方法来解决这个问题。我希望有人愿意帮助我。

1 个答案:

答案 0 :(得分:0)

前四次迭代使用字符串替换和eval的解决方案:

def expand rational_fraction, iteration
  new_rational_fraction = rational_fraction[0..-iteration].gsub(/2$/, '2 + Rational(1, 2' + ')' * iteration)
  iteration += 1
  puts eval(new_rational_fraction)
  expand new_rational_fraction, iteration if iteration <= 4
end

expand "1 + Rational(1,2)", 1

# => 3/2
#    7/5
#    17/12
#    41/29

如果有人在实现递归函数时看到了不使用字符串操作和eval的方法,我会很高兴听到。

/编辑

知道了! (通过阅读其他人对Project Euler 57线程的回答):

# Recursive function is last = 1+1/(1+last)
def expand rational_fraction, iteration
  puts rational_fraction
  new_rational_fraction = 1+1/(1+rational_fraction) 
  iteration += 1
  expand new_rational_fraction, iteration if iteration <= 4
end

expand 1 + Rational(1,2), 1

# => 3/2
#    7/5
#    17/12
#    41/29