序言中前n个数字的总和



你好,有人能帮我计算前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.

这个有效,但我需要另一个实现。我不知道该如何改变。请帮助

@mbratch说了什么。

您正在计算的是一个三角数。如果你的家庭作业是关于三角数的,而不是关于学习递归思维,你可以简单地计算它:

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编译器可以将它们转化为迭代(详细信息请谷歌"尾递归优化")。

如果你想消除累加器,你需要做这样的事情:

sum(0,0).
sum(N,R) :-
N > 0 ,
N1 is N-1 ,
sum(N1,R1) ,
R is R1+N
.

稍微简单一点,但每次递归都会消耗另一个堆栈帧:如果N的值足够大,则执行将失败,并出现堆栈溢出。

sum(N, Sum) :-
Sum is (N + 1) * N / 2 .

既然您已经得到了很多关于代码的建议,那么让我加入一个片段(有点偏离主题)。

计数,更普遍地说,聚合,与其他关系型声明性语言(读SQL)相比,Prolog在这一领域并不突出。但一些特定于供应商的库让它更令人愉快:

?- aggregate(sum(N),between(1,4,N),S).
S = 10.

这是程序的"心脏":

sum(N,R):-
R=R+N,
N=N-1,
sum(N,R).

=/2谓词(注意/2表示它接受2个参数)是实例化谓词,而不是赋值或逻辑等价。它试图将自己的论点统一起来,使它们保持一致。因此,如果N不是0,那么R=R+N将总是失败,因为R永远不可能与R+N相同。同样,对于N=N-1:它总是会失败,因为NN-1永远不可能相同。

=/2(统一)的情况下,表达式是而不是。它们只是条件。因此,如果Y = 1,则X = Y + 1X1+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那里了解到,Turbo Prolog与GNU或SWI不同,它计算=/2的表达式。因此=将在给定的问题中起作用。然而,关于实例化(或"自由变量")的错误仍然是由我上面提到的相同问题引起的。

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 .

相关内容

  • 没有找到相关文章

最新更新