为什么这个求平方根的递归函数会给出错误的结果?

Why does this recursive function for square-roots give the wrong result?

我制作了这个用于计算平方根的尾递归函数:

sqrt x n a = if n == 0 then a else sqrt x (n - 1) (a + x/a)/2

出于某种原因,当 n 大于 1 时,它会给出错误的结果,这意味着当它不止一次被要求改进近似值 a 时。它 returns 随着 n 的增长越来越接近 0 的数字。我尝试以不同的方式实现相同的递归公式,如下所示:

sqrt x n = if n == 0 then 1 else (a + x/a)/2 where a = sqrt x (n - 1)

sqrt x = 1:map (\a -> (a + x/a)/2) (sqrt x)

而且一切正常。这只是第一个不起作用的示例,尽管我尝试了很多次,但我无法弄清楚原因。

表达式:

sqrt x n a = if n == 0 then a else  sqrt x (n - 1) (a + x/a)  / 2

解析为:

sqrt x n a = if n == 0 then a else <b>(sqrt x (n - 1) (a + x/a))</b> / 2

所以sqrt x (n-1) (a+x/a)被看作是除以二的分子。您应该在此处添加括号:

sqrt x n a = if n == 0 then a else sqrt x (n - 1) <b>((a + x/a) / 2)</b>

有了给定的 fix,我们可以计算出 5 的平方根:

Prelude> sqrt 5 10 1
2.23606797749979

根据Wikipedia,是:

2.23606797749978969640917366873127623544061835961152572427089…

所以这已经很接近了。