如何在prolog中编写数字分类器?

时间:2015-06-02 00:05:45

标签: prolog

第一次和Prolog一起玩,虽然我觉得我知道它基本上有什么好处,但我觉得很难完成任何事情。所以,我试图找到最容易的任务,甚至没有完成。

我认为这是因为我不知道prolog数据类型(数字)应该如何工作或者它们具有特殊的语法。

所以,我第一次尝试对偶数进行分类是:

even(0).
even(X) :- even(X-2).

结果:查询的堆栈溢出:even(2)。

所以我认为如果不是这样,那么也许就是:

even(0).
even(X+2) :- even(X).

偶数(2)的结果:错误。

所以我的简单问题是:如何在prolog中编写这样简单的东西?这一切都不起作用,因为我使用数字?

2 个答案:

答案 0 :(得分:3)

为什么不以正常的方式去做:

is_even(X) :-
    X /\ 0x1 =:= 0.

如果你想在没有约束参数的情况下在回溯时枚举非负偶数,那么这完全是另一回事。可能很容易说:

even(X) :-
    between(0, infinite, X),
    is_even(X).

您可以使用第二个定义:

?- even(X).
X = 0 ;
X = 2 ;
X = 4 ;
X = 6 . % and so on

is_even/1even/1之间存在一些差异:

  • is_even/1适用于任何整数,正数或负数
  • 令人惊讶的是,
  • is_even/1将用于评估整数的表达式,例如X = 3, ..., is_even(X + 1)。这是因为=:=接受任何一方的算术表达式。
  • even/1使用between/3,因此 X 的域名和错误条件与between/3的第三个参数相同。
  • 因此,even/1不适用于负整数或算术表达式。

但等等,还有更多!

显然,between(0, infinite, X)除了SWI之外几乎不能在任何Prolog中做到。因此,相反,您可以使用另一个将枚举正整数的谓词(列表长度):

even_f(X) :-
    length(_, X),
    is_even(X).

(感谢@false)

答案 1 :(得分:0)

使用is/2强制进行算术评估。就其本身而言,Prolog术语只是结构符号实体,X-2是arity 2的复合术语,-(X,2)

3 ?- write_canonical( X-2 ).
-(_,2)
true.

但是is用于算术表达式:

4 ?- Z is 5-2.
Z = 3.

因此,您的定义应为

even(X):-  X=:=0 -> true 
        ;  X > 0 -> Y is X-2, even(Y).

这种定义的缺点是它不能以生成方式调用,如even(X),以便一个接一个地生成所有的平均值。

只检查给定的数字。为简单起见,它忽略了负数并且总是对它们失败。