我一直在尝试通过构建简短的程序来学习 Haskell。我对函数式编程世界有点陌生,但已经做了大量的阅读。
我在 Haskell 中有一个相对较短的递归函数,用于使用牛顿法找到一个函数的根,达到浮点数允许的精度:
newtonsMethod :: (Ord a, Num a, Fractional a) => (a -> a) -> (a -> a) -> a -> a
newtonsMethod f f' x
| f x < epsilon = x
| otherwise =
newtonsMethod f f' (x - (f x / f' x))
where
epsilon = last . map (subtract 1) . takeWhile (/= 1)
. map (+ 1) . iterate (/2) $ 1
当我在 GHCi 中解释并插入时
newtonsMethod (\ x -> cos x + 0.2) (\ x -> -1 * sin x) (-1)
, 我得到 -1.8797716370899549
,这是调用值的牛顿方法的第一次迭代。我的第一个问题很简单:为什么它只递归一次?如果您发现此代码的结构方式有任何潜在改进或明显错误,也请告诉我。
我的第二个问题,稍微复杂一点,是这样的:是否有一些干净的方法来测试这个函数的父调用,看看它是否无法收敛,并相应地退出?
预先感谢您提供的任何答案!
最佳答案
它只运行一次,因为 -1.8...
小于 epsilon
,一个严格的正数。您想检查差值的绝对值是否在容差范围内。
获得此类代码的收敛诊断的一种方法是将结果生成为惰性列表,这与您找到 epsilon
的方式不同。使用 iterate
.这意味着您可以通过遍历列表来获得最终结果,但您也可以在导致它的结果的上下文中看到它。
关于haskell - 递归 Haskell;牛顿法 : Why Doesn't This Converge?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19720457/