我根据以下逻辑编写了以下程序:素数只能被1和它自身整除。所以我只是经历了将它划分为大于1且小于其自身的所有数字的过程,但我似乎遇到了问题,因为我将所有输入的数字都设为真。这是我的代码......
divisible(X,Y) :-
Y < X,
X mod Y is 0,
Y1 is Y+1,
divisible(X,Y1).
isprime(X) :-
integer(X),
X > 1,
\+ divisible(X,2).
提前致谢:)
答案 0 :(得分:9)
我是Prolog的初学者,但设法解决了你的问题。
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)).
主要问题是声明X mod Y is 0
。谓词is
有两个(左和右)参数,但左参数必须是一个常量或变量,它在谓词执行时已经统一。我只是交换了这些值。其余的代码用于检查数字2(这是素数)和数字少于2(不是素数)
我忘了提到比较Y < X
是错误的,因为您要测试2和X-1之间的所有数字,该比较包括X.
答案 1 :(得分:5)
这个答案是@lefunction's previous answer的后续行动。
isPrime2/1
与isPrime1/1
尽可能接近,并进行了一些重要更改(如下所示):
isPrime2(2) :- !. isPrime2(3) :- !. isPrime2(X) :- X > 3, X mod 2 =\= 0, N_max is ceiling(sqrt(X)), isPrime2_(X,3,N_max). isPrime2_(X,N,N_max) :- ( N > N_max -> true ; 0 =\= X mod N, M is N + 2, isPrime2_(X,M,N_max) ).
让我们查询!
?- time(isPrime1(99999989)). % 99,999,990 inferences, 5.082 CPU in 5.078 seconds (100% CPU, 19678881 Lips) true. ?- time(isPrime2(99999989)). % 20,002 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 13615185 Lips) true.
答案 2 :(得分:4)
X mod Y is 0
总是失败,因为is
左侧不允许使用任何表达式。
更改为0 is X mod Y
,或者更好地更改为X mod Y =:= 0
答案 3 :(得分:3)
agarwaen's accepted answer在大数字上表现不佳。这是因为它不是尾递归(我认为)。此外,您可以通过一些关于素数的事实来加速一切。
1)2是唯一偶数素数
2)任何大于原件一半的数字均不均匀
isPrime1(2) :-
!.
isPrime1(3) :-
!.
isPrime1(X) :-
X > 3,
( 0 is X mod 2
-> false
; Half is X/2,
isPrime1_(X,3,Half)
).
isPrime1_(X,N,Half) :-
( N > Half
-> true
; 0 is X mod N
-> false
; M is N + 2,
isPrime1_(X,M,Half)
).
1 ?- time(isPrime1(999983)).
% 1,249,983 inferences, 0.031 CPU in 0.039 seconds (80% CPU, 39999456 Lips)
true.
<强> EDIT1 强>
是否可以更进一步? isPrime_/3
比isPrime2/1
更有效,因为它只与之前已知的素数进行比较。但问题是生成此列表。
allPrimes(Max,Y) :-
allPrimes(3,Max,[2],Y).
allPrimes(X,Max,L,Y) :-
Z is X+2,
N_max is ceiling(sqrt(X)),
( X >= Max
-> Y = L;
( isPrime_(X,L,N_max)
-> append(L,[X],K), %major bottleneck
allPrimes(Z,Max,K,Y)
; allPrimes(Z,Max,L,Y)
)).
isPrime_(_,[],_).
isPrime_(X,[P|Ps],N_max) :-
( P > N_max
-> true %could append here but still slow
; 0 =\= X mod P,
isPrime_(X,Ps,N_max)
).
答案 4 :(得分:2)
正在尝试其他方法。基于Fermats little theorem的伪素数测试:
test(P) :- 2^P mod P =:= 2.
test2(P) :- modpow(2,P,P,2).
modpow(B, 1, _, R) :- !, R = B.
modpow(B, E, M, R) :- E mod 2 =:= 1, !,
F is E//2,
modpow(B, F, M, H),
R is (H^2*B) mod M.
modpow(B, E, M, R) :- F is E//2,
modpow(B, F, M, H),
R is (H^2) mod M.
没有谓词{{1}},事情会变得太慢或整数溢出:
modpow/4
尚不确定如何将其扩展到完整的素数测试。
答案 5 :(得分:0)
我的方式是优雅的方式:
isPrime(A):-not((A1 is A-1,between(2,A1,N), 0 is mod(A,N))),not(A is 1).
1不是PRIME NUMBER,但如果您不这么认为,只需删除 not(A is 1)。