我知道..标题不是很好解释...如果你有一个更好的标题在评论中告诉我..
我正在制作一个素数生成器有趣和学习的目的..
这是我的代码:
divisors x xs = [ y | y <- [1]++xs++[x], x `mod` y == 0]
isPrime x xs = divisors x xs == [1,x]
primeLst = [ x | x <- [2..], isPrime x primeLst]
正如你所看到的那样..我必须在生成新的素数时使用已经生成的质数来减少执行时间..
它并没有工作..
有没有办法制作它?
答案 0 :(得分:2)
让我们从查看divisors
函数开始。这有点正确,只有两个问题:
xs
参数应该是什么?从定义来看,它看起来应该是x
以下的所有素数 - 让我们把它们称为候选素数。因此,如果x
为10
,则候选素数应为[2,3,5,7]
。但是,这不是函数作为参数获得的内容。在您的代码中,xs
是素数的无限列表。
从技术上讲,divisors
不会返回所有除数。例如,divisors 16 [2,3,5,7,11,13]
不会返回8
。但这是一个小小的挑剔。
因此,如果我们可以使用正确的素数列表调用divisors
,那么我们应该没问题,isPrime
函数也可以。
问题在于获得候选素数列表。为清楚起见,我将首先给出代码,然后解释:
primeLst = 2 : [ x | x <- [3..], isPrime x (takeWhile (\p -> p*p <= x) primeLst)]
我做了两处修改:
我确保primeLst
包含2
,并将其粘贴在前面。
我通过从无限的素数列表中取数来限制候选素数,直到我达到的数字高于我测试的素数的平方根。在这样做时,我稍微改变了候选素数的定义,因此例如26
的候选者是[2,3,5]
而不是[2,3,5,7,11,13,17,19,23]
。但它仍然有效。
您需要考虑两个问题:
为什么它仍适用于候选素数的新定义?
为什么以下代码行不起作用,即使它似乎应该给出候选素数的原始定义?
primeLst = 2 : [ x | x <- [3..], isPrime x (takeWhile (\p -> p < x) primeLst)]
最后一个问题很难,所以如果您有疑问,请在评论中发布。
答案 1 :(得分:2)
dividedBy a b = a `mod` b == 0
isPrime x = null $ filter (x `dividedBy`) $ takeWhile (\y -> y * y <= x) primeLst
primeLst = 2:(filter isPrime [3..])
或者,更详细:
primeLst = 2:(filter isPrime [3..])
where
isPrime x = null $ primeDivisors x
primeDivisors x = filter (x `dividedBy`) $ potentialDivisors x
potentialDivisors x = takeWhile (\y -> y * y <= x) primeLst
a `dividedBy` b = a `mod` b == 0
答案 2 :(得分:1)
计算primeLst
的至少一个元素需要计算isPrime 2 primeLst
,这需要计算divisors 2 primeLst
的至少两个元素,这需要至少计算[1]++primeLst++[2]
的两个元素,这需要计算primeLst
的至少一个元素。不会发生。
您可以制作使用[1]++(primesLessThan x)++[x]
的作品,但我没有看到用(primesLessThan x)
来定义primeLst
的简单方法,这可以避免计算循环。