【问题标题】:Project Euler - How is this haskell code so fast?Project Euler - 这个haskell代码怎么这么快?
【发布时间】:2014-02-19 00:19:42
【问题描述】:

我正在处理项目 euler 中的问题 401,我在 python 中编写了我的解决方案,但它需要几天时间才能运行,显然我需要加快速度或使用不同的方法。我在 Haskell 中遇到了一个看起来与我的 python 解决方案几乎相同但几乎瞬间完成的解决方案。

有人能解释一下它怎么这么快吗? (我不是在寻求帮助或解决问题 401

divisors n = filter (\x -> n `mod` x == 0) [1..(n`div`2)] ++ [n]
sigma2 n = sum $ map (\x -> x * x) (divisors n)
sigma2big n = sum $ map (sigma2)[1..n]
let s2b = sigma2big 10^15
putStrLn ("SIGMA2(10^15) mod 10^9 is " ++ (show (mod s2b 10^9)))

据我了解,它只是使用试除法生成一个除数列表,对它们进行平方和求和,然后将结果从 1 到 n 求和。

编辑:忘记了我的 python 代码

from time import clock


def timer(function):

    def wrapper(*args, **kwargs):
        start = clock()
        print(function(*args, **kwargs))
        runtime = clock() - start
        print("Runtime: %f seconds." % runtime)

    return wrapper


@timer
def find_answer():
    return big_sigma2(10**15) % 10**9

def get_divisors(n):
    divs = set()
    for i in range(1, int(sqrt(n)) + 1):
        if n % i == 0:
            divs.add(i)
            divs.add(n // i)
    return divs

def sigma2(n):
    return sum(map(lambda x: x**2, get_divisors(n)))

def big_sigma2(n):
    total = 0
    for i in range(1, n + 1):
        total += sigma2(i)
    return total

if __name__ == "__main__":
    find_answer()

【问题讨论】:

  • 如果您也向我们展示您的 Python 代码,那肯定会有所帮助。
  • 真正的问题可能是:为什么你的 Python 代码这么慢。
  • 我不知道 Haskell,但我对为什么你的代码这么慢的两个猜测是你的代码构建了明确的列表并设置了 Haskell 代码懒惰的地方,而 Haskell 被编译为本机Python是字节码解释的代码。特别是,如果这是 Python 2,range(1, 10**15+1) 会吃掉你所有的内存。
  • 有趣的是,几天后结束时,你将不知道它是否真的正确,因为它只是忽略了结果......
  • @abarnert 是的,我省略了使用装饰将代码包装在计时器中的部分,否则它确实不会显示结果。

标签: python haskell python-3.x


【解决方案1】:
Prelude> sigma2big 1000
401382971
(0.48 secs, 28491864 bytes)

Prelude> sigma2big 10^3
103161709
(0.02 secs, 1035252 bytes)

Prelude> (sigma2big 10)^3
103161709

函数优先级(嘘...)

【讨论】:

  • 天哪,我不敢相信我没有注意到...非常感谢。
【解决方案2】:

确保您使用Integer 进行计算,而不是Int,因为10^15 会溢出Int 值。

如果你改变:

let s2b = sigma2big 10^15

到:

let s2b = sigma2big (10^15 :: Integer)

ghci 中的 Haskell 代码内存不足,运行编译版本时我没有费心等待它完成。

【讨论】:

  • haskell代码不是我的,python代码是我写的。我想知道为什么 haskell 代码比我的要快得多。
  • 这是不正确的。正如另一个答案所指出的,这是您看到的 (sigma2big 10)^15 /= sigma2bit (10^15) 的区别。默认情况下,其他模棱两可的 Integrals 的类型默认实际上是 Integer
猜你喜欢
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 2017-01-10
  • 2020-12-19
  • 2011-06-02
  • 2012-03-18
  • 2011-05-27
相关资源
最近更新 更多