Prolog中数字是否为素数的计算

Prolog中数字是否为素数的计算,prolog,primes,primality-test,Prolog,Primes,Primality Test,我正在尝试计算输入是否是质数,但出现了一些问题。。。这是我的密码: 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). primeNumber(X):- 素数(A,1)。 素数(A,

我正在尝试计算输入是否是质数,但出现了一些问题。。。这是我的密码:

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).
primeNumber(X):-
素数(A,1)。
素数(A,B):-
R是一个mod B,
R=:=1,
R=:=A。
素数(X,B):-
B
它每次都给我
false
。有人知道我做错了什么吗?

请参阅:

+IntExpr1 mod+IntExpr2

模,定义为结果=IntExpr1-(IntExpr1 div IntExpr2)×IntExpr2,其中div是地板除法

所以
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\u 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.
为了进一步减少迭代次数,只需测试奇数模块:

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)).

Kay已经提供了对中断程序的工作修改。我将对损坏的内容进行简单分析

在Prolog中解决问题时,最好能够逻辑地写出您首先想要的是什么。在这种情况下,您似乎要声明:

A number, A, is prime if, for each number B < A, the value of A mod B is non-zero.
如果对于每个数B
可能有几种方法可以将其直接呈现到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.
如果:
(规则1)对于给定的B值,A模B的值是1,也是A。
或者(规则2)B
如您所见,定义的规则存在一些问题:

  • 这些规则与素数的逻辑定义不匹配,而素数的逻辑定义是根据原始数与小于其自身的所有数之间的模关系来描述的
  • 当A不等于1时,第一条规则需要一个不可能的数学条件(记住,Prolog中的逗号[,]是连词)
  • 这些规则是以1的起始除数开始的,这可能是不好的,因为1可以将所有东西除数,并且很可能成为任何有效规则的例外
编辑

回到使用模算子的质数的第一个定义,我们可以将其转换为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).
是素数(N):-%N是素数,如果。。。
N>1,%N>1,以及
(N,2)中不可除的%N不能被从2到N-1的所有事物整除
(N,D)中不可除的-%N是不可除的,如果。。。
N==N
%或者--
不可除的(N,D):-%N是不可除的,如果。。。
N>D,%N>D,和
N mod D=\=0,%N不可被D整除,且
D1是D+1,%N不能被D+1到N-1整除
(N,D1)中不可除的。

这个逻辑与Kay的基本相同,只是他使用了一个Prolog if-then-else结构。

首先:
X
a
:加载文本时查看警告。除非
a
1
,否则
R=:=1
R==a
都是真的。我认为有更好的算法(和prolog实现)用于primeNumber/1。如果这不是一个简单的示例,并且您计划在任何实际应用程序中使用此谓词,我可以与您分享我上次是如何使用它的。迭代B直到sqrt(A),而不是直到A已经足够了。我的意思是您的条件B>=A(大量迭代只会产生热量)@SergeiLodyagin,你是对的。我更新了我的答案。将“succ(B,C)”更改为与“C是B+2”(并且从prime_prime(A,3,L)开始将减少两次迭代次数…@SergeiLodyagin,谢谢!实际上我不打算提供一个演示解决方案,如何在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).