【发布时间】:2015-02-17 21:25:16
【问题描述】:
有谁知道如何让这个 Haskell 代码更有趣?我在做Project Euler #14。 此代码运行时间为 4.029 秒:
collatz :: Int -> Int64 -> Int
collatz c 1 = c
collatz c k
| even k = collatz (c+1) (k `div` 2)
| otherwise = collatz (c+1) (3*k + 1)
main = do
print $ maximum (map (\i -> (collatz 1 i, i)) [1..1000000])
记忆 collatz 函数实际上增加了运行时间,所以我没有做任何记忆。 可比较的 C 代码运行时间为 0.239 秒:
int main(int argc, char *argv[])
{
int maxlength = 0;
int maxstart = 1;
for (int i = 1; i <= 1000000; i++) {
unsigned long k = i;
int length = 1;
while (k > 1) {
length += 1;
if (k % 2 == 0)
k = k / 2;
else
k = 3*k + 1;
}
if (length > maxlength) {
maxlength = length;
maxstart = i;
}
}
printf("%d, %d\n", maxlength, maxstart);
return 0;
}
Haskell 代码用 ghc -O3 编译,C 代码用 gcc -std=c99 -O3 编译。
【问题讨论】:
-
严格注释是第一件事,然后是
shiftR x 1而不是div x 2(是的,仍然缺少一些关键优化)。这使您与 C 保持惊人的距离。 -
这个特殊的 Project Euler 问题在过去引发了一大堆类似的性能问题。看看this search 以获得一堆建议。 This one 可能特别相关。
-
你有 LLVM 吗?它在我的机器上用 -O2 -fllvm 运行 1.3 秒。
-
是的,llvm 做了优化,使除法为右移,偶数测试为按位与。使用 -fllvm 编译代码,或者手动更改上述问题,我的代码现在运行时间为 0.420 秒。感谢大家的帮助。
标签: haskell