我正在尝试计算输入是否为素数但出现问题...这是我的代码:
primeNumber(X):-
prime_prime(A, 1).
prime_prime(A, B):-
R is A mod B,
R =:= 1,
R =:= A.
prime_prime(X, B):-
B < A,
Next is B + 1,
prime_prime(A, Next).
每次都给我false
。任何人都对我做错了什么有任何线索或想法?
答案 0 :(得分:3)
请参阅http://www.swi-prolog.org/pldoc/man?function=mod/2:
+IntExpr1 mod +IntExpr2
模数,定义为Result = IntExpr1 - (IntExpr1 div IntExpr2)×IntExpr2,其中div是floored division。
因此R
应为0
。 mod
只有一个结果。
一个有效的解决方案是:
primeNumber(A) :-
A > 1, % Negative numbers, 0 and 1 are not prime.
prime_prime(A, 2). % Begin iteration:
prime_prime(A, B) :- % Test if A divides by B without remainder
B >= A % The limit was reached?
-> true % Then it's prime.
; 0 is A mod B % B divides A without a remainder?
-> false % Then it's not prime.
; succ(B, C), % Otherwise: C is B + 1
prime_prime(A, C). % Test if C divides A.
顺便说一下,primeNumber/1
(一个名为primeNumber
的谓词,带有一个参数)是一个完全独立的谓词primeNumber/2
(同名,两个参数)。仅为起始值获取额外参数的“子函数”通常具有相同的名称。因此,除了prime_prime
之外,您应该只使用primeNumber
,但在Prolog中,您通常不使用camelCase。
使用Sergei Lodyagin在评论中提出的优化:
primeNumber(A) :-
A > 1, % Negative numbers, 0 and 1 are not prime.
sqrt(A, L), % A prime factor of A is =< the square root of A.
prime_prime(A, 2, L). % Begin iteration:
prime_prime(A, B, L) :- % Test if A divides by B without remainder
B >= L % The limit was reached?
-> true % Then it's prime.
; 0 is A mod B % B divides A without a remainder?
-> false % Then it's not prime.
; succ(B, C), % Otherwise: C is B + 1
prime_prime(A, C, L). % Test if C divides A.
如果您使用预定义谓词between(+Low, +High, ?Value)
:
primeNumber(A) :-
L is floor(sqrt(A)),
\+ (between(2, L, X),
0 is A mod X).
为了进一步减少迭代次数,您只需要测试奇数模块:
primeNumber(2).
primeNumber(A) :-
A > 2,
\+ 0 is A mod 2,
L is floor(sqrt(A) / 2),
\+ (between(1, L, X),
0 is A mod (1 + 2*X)).
答案 1 :(得分:2)
当解决Prolog中的问题时,最好能够逻辑地写出你想要的东西。在这种情况下,您似乎要声明:
A number, A, is prime if, for each number B < A, the value of A mod B is non-zero.
可能有几种方法可以直接将其呈现给Prolog,其中Kay显示了一个。
但是,原始规则的编写方式,他们说:
A number, A, is prime if:
(Rule 1) The value of A mod B, for a given value of B, is 1 and is also A.
OR (Rule 2) B < A and Rule 1 is satisfied with A and B+1.
如您所见,定义的规则存在一些问题:
修改强>
使用模运算符返回 prime 的第一个定义,我们可以将其转换为Prolog,如下所示:
is_prime(N) :- % N is prime if...
N > 1, % N > 1, and
non_divisible_from(N, 2). % N is non-divisible by everything from 2 to N-1
non_divisible_from(N, D) :- % N is non-divisible by D through N-1 if...
N =< D. % D >= N
% --OR--
non_divisible_from(N, D) :- % N is non-divisible from D to N-1 if...
N > D, % N > D, and
N mod D =\= 0, % N is non-divisible by D, and
D1 is D + 1, % N is non-divisible by D+1 to N-1
non_divisible_from(N, D1).
这个逻辑与Kay的基本相同,只是他使用的是Prolog if-then-else结构。