在 Haskell 中为 Newton-Raphson 方法使用函数参数

问题描述 投票:0回答:1

我需要编写一个 Haskell 函数,通过传递一个函数、它的导数和初始点 (x0) 作为参数来解析 Newton-Raphson 算法,并返回函数根的近似值。

例子:

f(x) = x^2 − 2x + 1
f′(x) = 3x^2 − 2
x0​ = −1.5
.
x3 ​= −1.618 ​= x2​ − f′(x2​)/f(x2​)

非常感谢您的所有帮助和建议。

我之前试过的是这样的:

newtonR f g x0 = 
    if (x0 - (f x0 / g x0)) /= 0 then
        newtonR f g (x0 - f x0 / g x0)
    else
        x0

... 并返回以下错误消息:

No instance for (Show (Double -\> Double))
arising from a use of \`print'
(maybe you haven't applied a function to enough arguments?)
function haskell functional-programming newtons-method
1个回答
2
投票

可以从编写一个执行牛顿-拉夫森单次迭代的函数开始。请注意,在函数体之前提供显式类型签名是一种很好且常见的做法:

nrIter :: (Double -> Double) -> (Double -> Double) -> Double -> Double
nrIter f f' x0 = x0 - (f x0 / f' x0)

Haskell 的一个特点是

f'
是一个有效的标识符,这与经典的命令式语言不同。

如评论中所述,由于不可避免的舍入错误,测试浮点数是否相等很容易出错。相反,我们可以提供一个明确的公差级别,并像这样为 Newton-Raphson 编写上层逻辑:

newtonR :: (Double -> Double) -> (Double -> Double) -> Double -> Double -> Double
newtonR f f' tol x0 =
    let
         x1 = nrIter f f' x0
         dx = abs (x1 -x0)
    in   
         if (dx < tol)  then  x1
                        else  newtonR f f' tol x1

示例测试代码:

我们可以这样计算 2 的立方根的近似值:

main :: IO ()
main = do
    let  cr2 = newtonR  (\x -> x^3 - 2.0)  (\x -> 3.0*x^2)  1.0e-9  1.0
    putStrLn $ "Cubic root of 2 is close to: " ++ (show cr2)

© www.soinside.com 2019 - 2024. All rights reserved.