Prolog对我来说是新手。我正在尝试理解这段代码。如果有人能用儿童语言逐步解释这将是一个很大的帮助;)谢谢你!
divide_by(X,D,I,R) :-
X < D,
I is 0,
R is X.
divide_by(X,D,I,R) :-
X >= D,
Q is X - D,
divide_by(Q, D, S, R),
I is S +1.
答案 0 :(得分:3)
谓词描述的是什么关系?
实际上,这很难回答,因为我们会一步一步地完成它。但是有一种更好,更清洁的方式!由于您的程序仅使用整数,我们可以将模式化关系(<)/2
,(is)/2
等映射到CLP(FD)中的声明对应关系。因此,我将<
更改为#<
,将is
更改为#=
,将>=
更改为#>=
。
:- use_module(library(clpfd)).
divide_by(X,D,I,R):-
X #< D, I #= 0, R #= X.
divide_by(X,D,I,R):-
X #>= D, Q #= X - D,
I #= S +1,
divide_by(Q, D, S, R).
现在最大的优势是我可以向Prolog询问它认为关系所描述的内容。只需询问:(不要担心Q=Q
,只是重新排序变量)
N
... dividend D
... divisor Q
... quotient R
...余下?- Q=Q, divide_by(N,D,Q,R).
Q = 0,
N = R,
R#=<D+ -1
这个答案如下:商为零,被除数和余数相同,余数小于除数。所以这描述了0是“结果”或商的所有情况。
下一个回答:
;
Q = 1,
R+D#=N,
N#>=D,
R#=<D+ -1
商是1,被除数是除数加上余数,而且 - 如同所有答案一样 - 余数小于除数
;
Q = 2,
_G1665+D#=N,
N#>=D,
R+D#=_G1665,
_G1665#>=D,
R#=<D+ -1
此答案与R+D+D#= N
相同。系统引入了一些额外的变量。没错,但读起来有点笨拙。
;
Q = 3,
_G1930+D#=N,
N#>=D,
_G1951+D#=_G1930,
_G1930#>=D,
R+D#=_G1951,
_G1951#>=D,
R#=<D+ -1
;
Q = 4,
_G2195+D#=N,
N#>=D,
_G2216+D#=_G2195,
_G2195#>=D,
_G2237+D#=_G2216,
_G2216#>=D,
R+D#=_G2237,
_G2237#>=D,
R#=<D+ -1 ...
等等。让我总结一下。所有答案都是这样的:
N#>=D, R#< D, R+D+...+D#= N
^^^^^^^ Q times
甚至更好:
N#>=D, R #< D, R+Q*D #= N, Q #>= 0.
所以我们回答的是这个关系所描述的。
当你启动Prolog时,请关注声明方面。正如谓词所描述的那样(集合/关系)。程序方将在以后不加努力地加入。
答案 1 :(得分:1)
第一条规则称为base case
。它将终止递归。
divide_by(X,D,I,R):-
X < D, % this rule apply only if numerically X is < D
I is 0, % will fail if I \= 0
R is X. % if I = 0 assign expression X to R
这是另一个递归步骤。
divide_by(X,D, I, R):-
X >= D, % this rule apply only if X is >= D
Q is X - D, % evaluate Q
divide_by(Q, D, S, R), % recursive call. Q & D are surely instantiated
I is S + 1. % evaluate I as S + 1
所以,我会说:它将计算X的整数除以D,其余为R,在模式divide_by(+,+,-,-)
中调用时,即前两个参数绑定到整数最后两个免费。
无论如何,错误的答案是非常好的,因为它显示了一种可能的方法来推理“常见”编程语言中没有的算法。