私はこのコードをF#に入れています。このコードは、1から20までのすべての数字で均等に割り切れる最小の正の数を見つけます。F#末尾再帰とSeqライブラリのパフォーマンスの差
let isDivisableByAll num (divisors: int[]) = Array.forall (fun div -> num % div = 0) divisors
let minNumDividedBy (divisors: int[]) =
let rec minNumDividedByAll stopAt acc =
if acc >= stopAt then 0
else if isDivisableByAll acc divisors then acc
else minNumDividedByAll stopAt (acc + 1)
minNumDividedByAll 400000000 1
minNumDividedBy [|1..20|]
私はより少ないコードを好み、次のように書いていたので、よりエレガントにすることができると思いました。
let answer = { 1..400000000 }
|> Seq.tryFind (fun el -> isDivisableByAll el [|1..20|])
10分かかりました。シーケンスが怠けているので、大きな違いは説明できませんでした。調査するために、私は命令的なループを書いた。
let mutable i = 1
while i < 232792561 do
if isDivisableByAll i [|1..20|] then
printfn "%d" i
i <- i + 1
8分かかりました。したがって、シーケンスの障害でもありません。だから、なぜ初期の関数はとても速いのですか?それは、尾の再帰のためにスタックを構築することを避けることはできません、それはできますか?なぜなら、スローな例の中にビルドされていると、私はかなりのスタックを期待していないからです。
私には分かりませんが、誰かが私に教えてくれますか?
ありがとうございます。
2番目の例では、すべての反復で新しい配列を割り当てています。その多くの反復にわたって、それは加算しなければならない。まず配列を作成してから反復を実行してみてください。 –
lazy = not fast :-) – s952163
もちろん、アルゴリズムの変更でこれを行うのははるかに簡単な方法です。 –