我需要生成给定范围(1到N之间)的素数列表。我开发了一种算法来检查一个给定的数字是否为素数并且它工作正常。问题在于检查范围内所有数字并打印它们的功能。这是我到目前为止开发的内容......
% P39 (*) A list of prime numbers.
% Given a range of integers by its lower and upper limit, construct a
% list of all prime numbers in that range.
:- ensure_loaded(p31). % make sure is_prime/1 is loaded
% prime_list(A,B,L) :- L is the list of prime number P with A <= P <= B
prime_list(A,B,L) :- A =< 2, !, p_list(2,B,L).
prime_list(A,B,L) :- A1 is (A // 2) * 2 + 1, p_list(A1,B,L).
p_list(A,B,[]) :- A > B, !.
p_list(A,B,[A|L]) :- is_prime(A), !,
next(A,A1), p_list(A1,B,L).
p_list(A,B,L) :-
next(A,A1), p_list(A1,B,L).
next(2,3) :- !.
next(A,A1) :- A1 is A + 2.
提前致谢:)
答案 0 :(得分:3)
在主要测试方面做得很好。但是,你的循环代码比你需要的代码更多,而且偏离轨道。根据您显示的代码示例,您可能需要这样:
generatePrime(X, Y, N) :-
between(X, Y, N),
isPrime(N).
了解这是如何运作的?
?- generatePrime(2, 10, X).
X = 2 ;
X = 3 ;
X = 5 ;
X = 7 ;
false.
那些;
由人类操作员交互给出。
如果你想打印出所有这些,你可以选择经典的故障驱动循环:
generatePrime(X, Y) :-
between(X, Y, N),
isPrime(N),
write(N), nl,
fail.
generatePrime(_, _).
我不推荐这个,但由于某种原因,失败驱动的循环似乎是初学者的热门话题。我更倾向于做这样的事情:
generatePrimes(X, Y) :-
forall(
(between(X, Y, N), isPrime(N)),
(write(N), nl))).
无论哪种方式,你基本上都在那里,而且你有很多选择。
现在,一些特别说明:
isPrime(2).
基本上与isPrime(2) :- true, !.
的内容相同。我建议您在刚刚开始时远离剪辑。你几乎从来不需要一个明确的true
。not/1
不是ISO。请改用\+/2
(即\+ divisible(X, 2)
)X is 1
并不比X = 1
好。只有在右侧需要评估并存储在左侧命名的变量中时,才需要is/2
。 is/2
的其他通话约定要么不奏效,要么效率不高。X is X+1
将永远失败。 Prolog有variables, not assignables。您无法更改变量的值。您只能在其他地方安排绑定以具有特定值,可能是递归的。在这种情况下,正确的做法是X1 is X+1, generatePrime(Y, X1)
。大多数(但不是全部)预期的分配用途可以与此类似地处理。isPrime(X) -> write(X) ; true
会做正确的事而不被括号括起来;这是Prolog语法的一个区域,通常会让我感到兴奋,因此我几乎总是将整个条件表达式括起来以使其正确。另外,我认为你不需要; true
。答案 1 :(得分:0)
divisible(X,Y) :- 0 is X mod Y, !.
divisible(X,Y) :- X > Y+1, divisible(X, Y+1).
isPrime(2) :- true,!.
isPrime(X) :- X < 2,!,false.
isPrime(X) :- not(divisible(X, 2)).
primeR(A,B):- A =< B,(isPrime(A)->print(A), write(' '),A1 is A + 1; A1 is A + 1),primeR(A1,B).
输出:
?- [primet].
true.
?- primeR(1,20).
2 3 5 7 11 13 17 19
false.