【问题标题】:Stopping an iterate loop by a condition and returning the value that matched the condition通过条件停止迭代循环并返回与条件匹配的值
【发布时间】:2019-05-18 21:57:16
【问题描述】:

我正在尝试在 Haskell 上实现 Newton-Raphson 方法,到目前为止,我已经设法通过使用 iterate 函数使其工作,但问题是它会重新调整无限列表,因为它的性质迭代函数,所以我正在寻找一种方法,当迭代中获得的值落入设定的误差范围时停止循环,并返回所述值

我在这里查看了一些博客文章甚至一些问题,但我对 haskell 还很陌生,并且对语法并不完全精通,所以对我来说,现在阅读代码示例或文档真的很困难。

f(x) 和 g(x)(导数)的定义无关:

newton x0 = iterate step x0
    where step xn = xn - ((f xn)/(g xn))

我目前正在通过在 GHCi 提示符中使用 take 4 $ newton 3.5 获取给定列表的第一个元素,但 iterate 返回的列表是无限的,所以我不能对其使用 tail 函数。

我的想法是在某处设置一个常量,margin = 0.0001 或类似的东西,当牛顿函数的最后一次迭代落在边距之后,iterate 函数停止,我得到了最终结果

【问题讨论】:

  • 也许你想考虑takeWhile
  • "iterate 返回的列表是无限的,所以我不能对它使用尾函数。" 为什么不呢? tail 在无限列表上运行良好。
  • 切线说明:如果您想使用具有不同功能和边距的newton,则将fgmargin 作为参数传递可能会很有用。
  • until 函数怎么样?

标签: haskell newtons-method


【解决方案1】:

仅使用标准函数的 duplode 答案的变体:

newton :: Double -> Double
newton x0 = (snd . head . dropWhile (not . goal)) (zip approxs (tail approxs)) 
    where
    approxs = iterate step x0
    step xn = xn - (f xn / g xn)
    goal (xa, xb) = abs (xb - xa) < margin

为了确定我们的目标是否已经达到,我们需要检查由iterate 生成的无限列表的相邻元素对。为此,我们使用了标准技巧,即用自己的尾部压缩列表。 (如果你觉得特别厚脸皮,可以考虑使用(zip &lt;*&gt; tail) approxs 而不是zip approxs (tail approxs)。这样你就不必在表达式中提到approxs 两次,这确实有点毫无意义。)

这给了我们一个无限的对列表,我们从中删除元素,直到一对组件之间的差异变得足够小。此时,我们提取剩余列表(一对)的头部并获取第二个组件。

【讨论】:

  • 我想说这个答案是一个明确的改进:如果“你想测试成对的连续值”,你最好从字面上测试 pairs 值:)
【解决方案2】:

您想测试由newton 生成的连续值对。这意味着 Prelude 中的dropWhile 还不够,因为它只测试单个元素。相反,您可以使用来自 MissingHdropWhileList 之类的东西:

newton :: Double -> Double
newton x0 = dropWhileList (not . goal) (iterate step x0) !! 1
    where
    step xn = xn - ((f xn)/(g xn))
    goal (xa:xb:_) = abs (xb - xa) < margin
    goal _ = False

!! 1 为您提供列表的第二个元素。虽然它是一个偏函数(如果列表没有第二个元素,它会失败),在这里它可以安全使用(因为iterate 生成一个无限列表,只要牛顿方法收敛,你就会有结果) .

【讨论】:

    【解决方案3】:

    采纳oisdk关于使用until的建议...

    until :: (a -> Bool) -> (a -> a) -> a -> a 
    

    ...对于实际上不生成列表的实现:

    newton :: Double -> Double
    newton = snd . until goal (move . snd) . move
        where
        step xn = xn - (f xn)/(g xn)
        move xn = (xn, step xn) -- The cheeky spelling is (,) <*> step
        goal (xa,xb) = abs (xb - xa) < margin
    

    值得将此与 melpomene's zip-based implementation 进行比较并注意相似之处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-08
      • 2011-08-31
      • 2014-10-14
      • 2023-03-06
      • 2014-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多