Euler 23 in C#: 0.2 seconds, in F#: 30.5 seconds. Why?

后端 未结 1 1057
南旧
南旧 2021-01-22 02:03

I am not really satisfied with my F# solution to this problem because I can\'t find a beautiful & fast solution, but that\'s not the issue here. The issue is, I translated t

1条回答
  •  迷失自我
    2021-01-22 02:29

    Your F# version isn't slow at all; it takes 0.44 seconds in F# Interactive on my machine. I don't know how you could observe such a slowness (30.5 seconds). If you compile and run the code, make sure that you're in Release mode and turning on optimization and tail call elimination.

    However, you still can optimize further by eliminating the use of redundant intermediate collections.

    A. Change (redundant) list [2..limit] to range expression 2..limit in divisorsSum:

    for i in 2..limit do
        if n%i=0 then sum <- sum+i+n/i
    

    B. Generate array of abundants without creating the big list (more faithful to C# version):

    let abundants = 
        let arr = ResizeArray(28123)
        for i in 1..28123 do
            if isAbundant i then arr.Add i
        arr.ToArray()
    

    C. Calculate solve without creating the big list:

    let solve = 
        loopUntil 0 0
        let mutable sum = 0
        for i in 1..28123 do
           if not <| domain.Get(i) then
                sum <- sum + i
        sum
    

    The new F# version is 4x faster than the original one; it takes about 0.1 seconds to complete.

    UPDATE:

    Your measurement is inaccurate. First, you measured time difference between two calls of printing values. Second, EulerXXX.solve are values; so they are pre-calculated when you compiled your program. You should declare EulerXXX.solve as functions:

    let solve() = ...
    

    and measure execution time of function calls:

    let time fn =
        let sw = new System.Diagnostics.Stopwatch()
        sw.Start()
        let f = fn()
        sw.Stop()
        printfn "Time taken: %.2f s" <| (float sw.ElapsedMilliseconds)/1000.0
        f
    
    let s023 = time Euler023.solve
    printf "Euler023 solution: %A" s023
    

    0 讨论(0)
提交回复
热议问题