我已经编辑了程序,以便它可以工作(使用小数字)但是我不明白如何按照建议实现累加器。原因是因为P在整个过程中都在变化,所以我不知道我应该以哪个粒度来分解母列表。Erastosthenes 的筛子只对生成较小的素数有效,所以也许我应该选择一个不同的算法来使用。有人可以推荐一个体面的算法来计算 600851475143 的最高素数吗?请不要给我代码我更喜欢这种性质的维基百科文章。
-module(sieve).
-export([find/2,mark/2,primes/1]).
primes(N) -> [2|lists:reverse(primes(lists:seq(2,N),2,[]))].
primes(_,bound_reached,[_|T]) -> T;
primes(L,P,Primes) -> NewList = mark(L,P),
NewP = find(NewList,P),
primes(NewList,NewP,[NewP|Primes]).
find([],_) -> bound_reached;
find([H|_],P) when H > P -> H;
find([_|T],P) -> find(T,P).
mark(L,P) -> lists:reverse(mark(L,P,2,[])).
mark([],_,_,NewList) -> NewList;
mark([_|T],P,Counter,NewList) when Counter rem P =:= 0 -> mark(T,P,Counter+1,[P|NewList]);
mark([H|T],P,Counter,NewList) -> mark(T,P,Counter+1,[H|NewList]).
我发现写这个非常困难,而且我知道它有一些不是很优雅的东西,比如我将 2 硬编码为质数的方式。因此,我将不胜感激任何 C&C 以及有关如何解决此类问题的建议。我查看了其他实现,我完全不知道作者如何以这种方式思考,但它是我想掌握的东西。
我已经弄清楚我可以忘记这个列表,直到找到最近的素数,但是我不知道我应该如何产生一个结束界限(微妙的幽默)。我认为可能有一些我可以使用的东西,比如 lists:seq(P,something) 并且当我使用模数而不是每次都将其重置为 0 时,计数器将能够处理它。我只做过AS级别的数学,所以我不知道这是什么。
我什至不能这样做,我可以吗?因为我将不得不从整个列表中删除 2 的倍数。我认为除非我将数据缓存到硬盘驱动器,否则该算法将不起作用,所以我重新寻找更好的算法。
我现在正在考虑编写一个算法,它只使用一个计数器并保留一个素数列表,这些素数是不与先前生成的素数均分的数字,这是一个好方法吗?
这是我写的新算法,我认为它应该可以工作,但我收到以下错误“sieve2.erl:7: call to local/imported function is_prime/2 is legal in guard”我认为这只是 erlang 的一个方面我不明白。但是,我不知道如何找到有关它的材料。[我故意不使用高阶函数等,因为我只在 learnyousomeerlang.org 中阅读了关于递归的部分内容]
-module(sieve2).
-export([primes/1]).
primes(N) -> primes(2,N,[2]).
primes(Counter,Max,Primes) when Counter =:= Max -> Primes;
primes(Counter,Max,Primes) when is_prime(Counter,Primes) -> primes(Counter+1,Max,[Counter|Primes]);
primes(Counter,Max,Primes) -> primes(Counter+1,Max,Primes).
is_prime(X, []) -> true;
is_prime(X,[H|T]) when X rem H =:= 0 -> false;
is_prime(X,[H|T]) -> prime(X,T).
第二个算法不会崩溃但运行得太慢,我想我应该重新实现第一个但这次忘记了直到最近发现的素数的数字,有人知道我可以用什么作为结束界限吗?在查看其他解决方案之后,似乎人们有时只是设置了一个任意限制,即 200 万(这是我真的不想做的事情。其他人使用“懒惰”的实现,这就是我认为我正在做的事情。