首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell性能调优

Haskell性能调优
EN

Stack Overflow用户
提问于 2015-04-02 12:57:06
回答 1查看 407关注 0票数 2

我对Haskell非常陌生,为了更好地学习它,我开始到处解决问题,最后得到了这个(Euler项目34)。

145是一个奇怪的数字,1 + 4 + 5!=1+ 24 + 120 = 145。 找出所有数字的和等于阶乘数的和>其数字的和。 注:由于1!=1和2不包括在内。

我写了C和Haskell蛮力的解决方案。

有人能解释一下,Haskell版本比C实现慢15x (~0.450 s vs ~6.5 s),如何优化和加速Haskell解决方案?

代码语言:javascript
复制
unsigned int solve(){
unsigned int result = 0;
unsigned int i=10;
while(i<2540161){
    unsigned int sumOfFacts = 0;
    unsigned int number = i;
    while (number > 0) {
       unsigned int d = number % 10;
        number /= 10;
        sumOfFacts += factorial(d);
    }
    
    if (sumOfFacts == i)
        result += i;
    
    i++;
 }
 return result;
}

这里是haskell解决方案

代码语言:javascript
复制
--BRUTE FORCE SOLUTION
solve:: Int
solve = sum (filter (\x-> sfc x 0 == x) [10..2540160])

--sum factorial of digits
sfc :: Int -> Int -> Int
sfc 0 acc = acc
sfc n acc = sfc n' (acc+fc r)
    where
        n' = div n 10
        r  = mod n 10   --n-(10*n')
        fc 0 =1
        fc 1 =1
        fc 2 =2
        fc 3 =6
        fc 4 =24
        fc 5 =120
        fc 6 =720
        fc 7 =5040
        fc 8 =40320
        fc 9 =362880
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-02 13:58:54

首先,使用优化进行编译。使用ghc-7.10.1 -O2 -fllvm,Haskell版本为我在0.54 secs中运行。这已经很不错了。

如果我们想做得更好,我们首先应该用quot代替quot,用rem代替moddivmod做了一些额外的工作,因为它们处理负数舍入的方法不同。因为这里只有正数,所以我们应该切换到更快的函数。

其次,我们应该将fc中的模式匹配替换为数组查找。GHC对Int模式使用分支结构,并在案例数量足够大时使用二进制搜索。我们只要查一下就能做得更好。

新代码如下所示:

代码语言:javascript
复制
import qualified Data.Vector.Unboxed as V

facs :: V.Vector Int
facs =
  V.fromList [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

--BRUTE FORCE SOLUTION
solve:: Int
solve = sum (filter (\x-> sfc x 0 == x) [10..2540160])

--sum factorial of digits
sfc :: Int -> Int -> Int
sfc 0 acc = acc
sfc n acc = sfc n' (acc + V.unsafeIndex facs r)
    where
        (n', r) = quotRem n 10

main = print solve

它在我的计算机上以0.095秒的速度运行。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29413564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档