【问题标题】:Linear recurrence relation implementation in Haskell too slowHaskell中的线性递归关系实现太慢了
【发布时间】:2012-01-09 12:31:50
【问题描述】:

我已经实现了一个代码,它在给定基本情况和线性递归关系的系数的情况下生成无限序列。

import Data.List
linearRecurrence coef base | n /= (length base) = []
                           | otherwise = base ++ map (sum . (zipWith (*) coef)) (map (take n) (tails a))
  where a     = linearRecurrence coef base
        n     = (length coef)

这是斐波那契数列的实现。 fibs = 0 : 1 : (zipWith (+) fibs (tail fibs))

很容易看出

linearRecurrence [1,1] [0,1] = fibs

但是计算fibs!!2000 的时间是 0.001 秒,(linearRecurrence [1,1] [0,1])!!2000 大约是 1 秒。速度上的巨大差异从何而来?我已经把一些功能变得严格了。例如,(sum . (zipWith (*) coef))(id $! (sum . (zipWith (*) coef))) 替换,并没有帮助。

【问题讨论】:

  • 您是否使用标准来衡量这一点?如果不是,请验证您的测量结果是否只是巧合。
  • 我刚刚在我的上网本上运行了这个标准(使用-O2),我发现两者之间的差异大约是 10 倍,而不是你声称看到的 1000 倍。

标签: haskell


【解决方案1】:

您正在重复计算linearRecurrence coef base。利用共享,如:

linearRecurrence coef base | n /= (length base) = []
                           | otherwise = a
  where a = base ++ map (sum . (zipWith (*) coef)) (map (take n) (tails a))
        n = (length coef)

注意a的分享。

现在你得到:

*Main> :set +s
*Main> fibs!!2000
422469...
(0.02 secs, 2203424 bytes)
*Main> (linearRecurrence [1,1] [0,1])!!2000
422469...
(0.02 secs, 5879684 bytes)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多