你好,任何人都可以帮我计算前n个数字的总和。例如,n = 4 => sum = 10。 到目前为止,我已经写了这个
predicates
sum(integer,integer)
clauses
sum(0,0).
sum(N,R):-
N1=N-1,
sum(N1,R1),
R=R1+N.
这个有效但我需要另一个实现。我没有任何想法如何使这种差异化。请帮忙
答案 0 :(得分:6)
@mbratch说的话。
您计算的是triangular number。如果你的作业是关于三角形数字而不是学习递归思维,那么你可以简单地计算它:
triangular_number(N,R) :- R is N * (N+1) / 2 .
如果您更有可能学习递归思维,请尝试以下方法:
sum(N,R) :- % to compute the triangular number n,
sum(N,1,0,R) % - invoke the worker predicate with its counter and accumulator properly seeded
.
sum(0,_,R,R). % when the count gets decremented to zero, we're done. Unify the accumulator with the result.
sum(C,X,T,R) :- % otherwise,
C > 0 , % - assuming the count is greater than zero
T1 is T+X , % - increment the accumulator
X1 is X+1 , % - increment the current number
C1 is C-1 , % - decrement the count
sum(C1,X1,T1,R) % - recurse down
. % Easy!
编辑添加:
或者,如果您更喜欢倒计时方法:
sum(N,R) :- sum(N,0,R).
sum(0,R,R). % when the count gets decremented to zero, we're done. Unify the accumulator with the result.
sum(N,T,R) :- % otherwise,
N > 0 , % - assuming the count is greater than zero
T1 is T+N , % - increment the accumulator
N1 is N-1 , % - decrement the count
sum(N1,T1,R) % - recurse down
. % Easy!
这两个都是尾递归,这意味着prolog编译器可以将它们转换为迭代(google“tail recursion optimization”以获取详细信息)。
如果你想消除累加器,你需要做这样的事情:
sum(0,0).
sum(N,R) :-
N > 0 ,
N1 is N-1 ,
sum(N1,R1) ,
R is R1+N
.
稍微简单一些,但是每次递归都会消耗另一个堆栈帧:给定N的值足够大,执行将因堆栈溢出而失败。
答案 1 :(得分:2)
sum(N, Sum) :-
Sum is (N + 1) * N / 2 .
答案 2 :(得分:2)
既然你已经对你的代码提出了很多建议,那么让我抛出一个片段(有点偏离主题)。
计数,更一般地说,聚合,与其他关系式声明性语言(读取SQL)相比,这是Prolog不会发光的区域。但是某些特定供应商library使其变得更加愉快:
?- aggregate(sum(N),between(1,4,N),S).
S = 10.
答案 3 :(得分:1)
这是您计划的“核心”:
sum(N,R):-
R=R+N,
N=N-1,
sum(N,R).
=/2
谓词(注意/2
表示它接受2个参数)是 instantiation 谓词,而不是赋值或逻辑相等。它试图统一其论点以使它们相同。因此,如果N
不是0
,那么R=R+N
将始终失败,因为R
永远不会与R+N
相同。同样适用于N=N-1
:它始终会失败,因为N
和N-1
永远不会相同。
在=/2
(统一)的情况下,表达式未评估。它们只是条款。因此,如果Y = 1
,则X = Y + 1
将X
与1+1
统一为一个术语(等效地写为+(1,1)
)。
由于上述问题,sum
将始终失败。
算术表达式的数值赋值在Prolog中使用is/2
谓词完成。像这样:
X is Y + 1.
此运算符将X
的值统一为,使其与已计算表达式Y+1
的值相同。在这种情况下,由于上面给出的相同原因,您也不能拥有X is X+1
:X
不能与X+1
相同而Prolog不允许对内部变量进行“重新实例化”一个条款。所以你需要像X1 is X + 1
这样的东西。另请注意,要使is/2
起作用,右侧表达式中的所有内容都必须先实例化。如果右侧表达式中的任何变量没有值,则会出现实例化错误,或者对于Turbo Prolog,表达式中的自由变量...
因此,您需要为表达式结果使用不同的变量,并组织代码,以便在使用is/2
时,实例化表达式中的变量。
我从Sergey Dymchenko那里了解到,与GNU或SWI不同,Turbo Prolog会评估=/2
的表达式。所以=
将在给定的问题中起作用。但是,关于实例化(或“自由变量”)的错误仍然是由我上面提到的相同问题引起的。
答案 4 :(得分:0)
sum(N, N, N).
sum(M, N, S):-
N>M,
X is M+1,
sum(X, N, T),
S is M+T.
?- sum(1,5,N).
N = 15 .