我是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
。
我认为这是see
或tell
。我重新分配see(user)
和tell(user)
,但此错误再次发生。
为什么呢?
答案 0 :(得分:6)
在您使用的SWI prolog 6.0.2分区中返回浮点数。因此prime(13)
将失败,因为余数为0.整数除法使用运算符//
。但请检查prolog SWI函数rem
和mod
。
此外,您希望在第一次定义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).
答案 1 :(得分:3)
关于您的错误,请查看:
?- 2+2.
ERROR: Undefined procedure: (+)/2
?- X is 2+2.
X = 4
你应该在Prolog中使用is
来强制评估算术表达式。尝试在SWI-Prolog的提示符下输入“help(is).
”。
但是你的算法在两个帐户上效率非常低。首先,您通过所有前面的数字检查候选编号的可分性,而只有那些不大于其平方根的候选编号就足够了(如果a*b=n
和a >= 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).
答案 2 :(得分:2)
您提到see
和tell
:这些都是非常老式的内置谓词。最好避免它们。使用[file]
加载文件,使用make
重新加载文件。
要更好地实施测试质数,请参阅this answer。