3

我是 SWI-Prolog 的新手,我想检查 Prolog 中的主要功能。

prime(N) :-
    N > 1,
    M is N - 1,
    check(N, M).

check(_, 1).
check(N, M) :-
    M > 1,
    R is N - M * N / M,
    R > 0,
    P is M - 1,
    check(N, P).

但是当我在 Prolog 中询问2 + 2或其他运算符时,如(*)/2, (/)/2,... 它会说:undefined procedure: (+)/2。我认为它适用于seeor tell。我重新分配see(user)tell(user)但此错误再次发生。为什么?

4

3 回答 3

6

在您使用的 SWI prolog 6.0.2 除法中,它返回浮点数。因此prime(13),例如将失败,因为余数为 0。整数除法使用 operator //。但检查 prolog SWI 函数remmod.

此外,您希望在第一个定义之后进行剪切check,否则 prolog 将探索第二个定义,这将返回 false。Cut 确保在检查所有小于 N 的自然数后,它会成功停止。

这是在 SWI Prolog 6.0.2 中按需要运行的更正代码。

prime(N) :-
    N > 1,
    M is N - 1,
    check(N, M).

check(_, 1) :- !.
check(N, M) :-
    M > 1,
    R is N mod M,
    R > 0,
    P is M - 1,
    check(N, P).
于 2012-06-11T10:23:18.580 回答
4

关于您的错误,请查看:

?- 2+2.
ERROR: Undefined procedure: (+)/2

?- X is 2+2.    
X = 4 

您应该is在 Prolog 中使用来强制计算算术表达式。尝试help(is).在 SWI-Prolog 的提示符下键入“”。

但是你的算法效率非常低,有两个原因。首先,您检查候选数是否可以被其前面的所有数字整除,而只有那些不大于其平方根的数字就足够了(如果a*b=na >= sqrt(n)然后b =< sqrt(n))。

然后,您以相反的顺序进行测试。较小因素的倍数比较大因素的倍数要频繁得多,因此当按升序完成时,测试会更早中断,从而使整个程序运行得更快。最后,不需要用除 2 以外的任何偶数进行测试:

prime(2).
prime(N) :- N > 1,
    N mod 2 > 0,              % is odd
    M is floor(sqrt(N+1)),    % round-off paranoia 
    check(N, M, 3).

check(N, M, F) :- F>M.
check(N, M, F) :- F=<M,
    N mod F > 0,
    F1 is F + 2,              % test by odds only
    check(N, M, F1).

primesFromTo(F,T,X):-
  between(F,T,X), prime(X).
于 2012-06-13T06:45:18.530 回答
2

您提到seeand tell:这些是非常老式的内置谓词。最好避开它们。用于[file]加载文件并make重新加载它。

有关测试素数的更好实施,请参阅此答案

于 2012-07-09T16:48:45.520 回答