使用固定点在第n个根中的错误

时间:2014-07-25 08:04:54

标签: debugging haskell numeric sicp

以下是我在Haskell中实施的计算机程序结构和解释练习1-45的尝试解决方案:

fixedpoint :: (Double->Double) -> Double -> Double -> Double
fixedpoint f guess err
  | err > abs next-guess  = next
  | otherwise             = fixedpoint f next err
  where next = f guess

avg :: Double -> Double -> Double
avg a b = (a+b)/2

avgdamp :: (Double -> Double) -> (Double -> Double)
avgdamp f = \ x -> avg x (f x)

log2 :: Double -> Double
log2 = (/ log 2) . log

repeated :: (a->a) -> Int -> (a->a)
repeated f n = \ x -> (iterate f x) !! n

nthroot :: Int -> Double -> Double -> Double
nthroot n x err = fixedpoint (repeated avgdamp numdampsneeded $ eqn) 1.0 err where
  numdampsneeded = floor $ log2 $ fromIntegral n  -- experimentally determined
  eqn = \ y -> x/y^(n-1)

我逐一测试了帮助程序,看起来很好。我查看了3个博客,其中发布了哪些解决方案,我的似乎与它们相对应,有一些小的例外,如实现语言,我使用显式错误参数。

尽管如此,我从nthroot得到了可笑的结果,我没有线索。

> nthroot 2 16 0.000000001
5.1911764705882355

> nthroot 3 8 0.000001
2.447530864197531

> nthroot 3 27 0.001
7.0688775510204085

> nthroot 5 32 0.001
6.563864764681383

或者在这种情况下,我期望像八度音阶那样回归(近似)[0..16]

 > [0:16].^(1/2).^2

ans =
    0.00000    1.00000    2.00000    3.00000    4.00000    5.00000    6.00000    7.00000    8.00000    9.00000   10.00000   11.00000   12.00000   13.00000   14.00000   15.00000   16.00000

> map (^2) $ map (\x -> nthroot 2 x 0.000001) [0..16]
[0.25,1.0,2.006944444444444,3.0625,4.2025,5.4444444444444455,6.79719387755102,8.265625,9.852623456790123,11.559999999999999,13.388946280991735,15.340277777777777,17.41457100591716,19.612244897959187,21.933611111111112,24.37890625,26.94831314878893]

对这些糟糕结果背后可能出现的任何猜测都是值得欢迎的。

1 个答案:

答案 0 :(得分:3)

函数应用程序比任何中缀运算符都更紧密。因此,

abs next - guess  ==  (abs next) - guess

这不是你想要的。如果您解决了这个问题,那么您的算法运行正常。