WikipediaのHaskellの項目、fib = 1:1:zipWith (+) fib (tail fib)が線形時間で動くって書いてあるけど、これ正しくないよね?
2010-06-22 14:00:54Haskellの「fib=1:1:zipWith(+) fib (tail fib)」は2.6乗のオーダーで時間がかかり、N = 100000ではPythonより遅い http://d.hatena.ne.jp/nishiohirokazu/20100622/1277208908
2010-06-22 21:21:36@nishio なんで遅くなるか良く分かっていないんですが、fib = map fst $ iterate (snd &&& uncurry (+)) (1,1) だとどうですか
2010-06-22 21:38:13@pi8027 冗長なコードと同程度に早ければね。僕の予想は1:1:zipWithと同等かさらに遅いってもので、それは正しかった。10万で1.9sec, 20万で19.1sec。激しく悪化している(笑)
2010-06-22 21:47:34@pi8027 ちなみに僕の想像が正しければ遅くなる理由(余計な0.6乗)はサンクの増殖が原因で、高速なバージョンが速いのは単に末尾再帰であることだけじゃなくてfib' 5 1 1を簡約したときにfib' 4 1 (1 + 1)になるだけでサンクが増えないからだ
2010-06-22 22:09:19@nishio じゃあ、Int -> (a -> a) -> a -> a みたいな型を持つ"関数をN回適用した結果を返す関数"があればいいんですよね。
2010-06-22 22:17:56@nishio 手元に今Haskellの実行環境がないので自信があまりないですが、下のものは+を正格評価しないとスタックが溢れたりしないでしょうか。上も遅延評価が影響したりしてないですかね。
2010-06-22 22:11:39@jmuk 上のが遅い理由は遅延評価だと思います。下のはfib 4 1 (1 + 1)のパターンマッチで1 + 1の評価が強制されるのでseqとかしないでも大丈夫です。
2010-06-22 22:18:14@nishio それは処理系次第ですよ。iter (n+1) f a が iter n f (f a) になればいい。
2010-06-22 22:22:48http://www.haskell.org/haskellwiki/The_Fibonacci_sequence ほー
2010-06-22 22:58:09@nishio ようやく実行環境を整えました。上は遅延評価ですね。下も-O3でないと評価が遅延されて遅いかと。zipWith'みたいな関数を定義すれば普通に速いかと。
2010-06-23 00:49:27zipWith'は既に試してましたが,zipWithより2倍ぐらい遅くなったので「遅延だから」というのは違うと思います. zipWith' f (x:xs) (y:ys) = ((f $! x) $! .. http://togetter.com/li/31078
2010-06-23 10:01:10Integer加算の分を考えると話が複雑になるので、とりあえず0,0から始めてみる http://codepad.org/FgRsOFi7 と、at0 と at1 が同じくらい(当たり前)で、at2 が圧倒的に速い。速いのは当然なんだけどオーダが違うように見えるのは、えーと…
2010-06-23 12:43:54