簡體   English   中英

為什么這個Haskell表達式如此之慢?

[英]Why is this Haskell expression so slow?

我正在研究Project Euler Problem 14.這是我的解決方案。

import Data.List

collatzLength :: Int->Int
collatzLength 1 = 1
collatzLength n | odd n = 1 + collatzLength (3 * n + 1)
                | even n = 1 + collatzLength (n `quot` 2)

maxTuple :: (Int, Int)->(Int, Int)->Ordering
maxTuple (x1, x2) (y1, y2)  | x1 > y1 = GT
                | x1 < y1 = LT
                | otherwise = EQ

我正在運行以下GHCi

maximumBy maxTuple [(collatzLength x, x) | x <- [1..1000000]]

我知道如果Haskell嚴格評估,那么這個時間就像O(n 3 )。 由於Haskell懶惰地評估,看起來這應該是n的一些常數倍。 這已經運行了近一個小時了。 似乎很不合理。 有誰知道為什么?

您假設collatzLength函數將被記憶。 Haskell不進行自動記憶。 你需要自己做。 這是使用data-memocombinators包的示例。

import Data.List
import Data.Ord
import qualified Data.MemoCombinators as Memo

collatzLength :: Integer -> Integer
collatzLength = Memo.arrayRange (1,1000000) collatzLength'
  where
    collatzLength' 1 = 1
    collatzLength' n | odd n  = 1 + collatzLength (3 * n + 1)
                     | even n = 1 + collatzLength (n `quot` 2)

main = print $ foldl1' max $ [(collatzLength n, n) | n <- [1..1000000]]

當使用-O2編譯時,這將在大約1秒內運行。

為了能夠找到最大列表,需要評估整個列表。

所以它將從11000000計算collatzLength並且collatzLength是遞歸的。 最糟糕的是,你對collatzLength的定義甚至不是尾遞歸的。

cLcollatzLength

cL!!n代表collatzLength n

cL :: [Int]
cL = 1 : 1 : [ 1 + (if odd n then cL!!(3*n+1) else cL!!(n `div` 2)) | n <- [2..]]

簡單測試:

ghci> cL !! 13
10

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM