performance - 合并功能要慢得多

标签 performance haskell primes primality-test

我写了 isPrime 函数。它检查给定的数字是否为素数。
最后一个“主要”列表是单独给出的。

prime :: [Integer]
prime = 2 : filter isPrime [3..]
isPrime :: Integer -> Bool
isPrime n | n < 2 = False
isPrime n = all (\p -> n `mod` p /= 0) . takeWhile ((<=n) . (^2)) $ prime

我认为如果可能的话,将两个函数合并为一个总是更好。所以我将 isPrime 和 prime 合并为一个函数 isPrime2。但是isPrime2的性能很差。
isPrime2 :: Integer -> Bool
isPrime2 n | n < 2 = False
isPrime2 n = all (\p -> n `mod` p /= 0) . takeWhile ((<=n) . (^2)) $ 2 : filter isPrime2 [3..]

是素数 40000000000000000001

=> 0.5 秒

isPrime2 400000000000000000001

=> 19.8 秒

我的机器是 Ubuntu 17.10 x86-64。我正在使用 ghc 8.2.1。有谁知道为什么?

最佳答案

第一个片段将只保留一个列表 prime s 在内存中。

第二个片段将计算自己的 prime直到 n^2每一次isPrime2叫做。以前发现的素数在每次调用时都会被丢弃并重新计算。
由于isPrime2是递归的,这会导致爆炸。

一种中间方法可以是这个:

isPrime2 :: Integer -> Bool
isPrime2 m = isPrime m
   where
   prime :: [Integer]
   prime = 2 : filter isPrime [3..]
   isPrime :: Integer -> Bool
   isPrime n | n < 2 = False
   isPrime n = all (\p -> n `mod` p /= 0) . takeWhile ((<=n) . (^2)) $ prime

这将重新计算 prime每次调用isPrime2 ,但不会导致崩溃,因为内部 isPrime 的每次调用将共享 prime 的相同列表s。

关于performance - 合并功能要慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47012718/

相关文章:

haskell - liftM2的懒人版

java - 如何确定极大的质因数?

php - 大 cookie 导致应用程序运行缓慢

python - 调试语句级性能的正确方法

haskell - 从哪里开始阅读 GHC 的源代码

performance - 使用 Data.ByteString 实现 unix 的 "cat"程序的 Haskell 性能

c - 我们如何从 Julia 调用 primesieve C 库?

c++ - 为什么大数输入会导致此代码计算 primeCounting 时产生运行时错误?

performance - 为超大数据选择数据结构

django - 在 Django 中使用用户配置文件检索用户的最有效方法