Loops 如何在Prolog中计算数列和

Loops 如何在Prolog中计算数列和,loops,prolog,Loops,Prolog,任务是计算从0到M的自然数之和。我使用SWI Prolog编写了以下代码: my_sum(From, To, _) :- From > To, !. my_sum(From, To, S) :- From = 0, Next is 1, S is 1, my_sum(Next, To, S). my_sum(From, To, S) :- From > 0, Next is From + 1, S is S + Next, my_sum(Next, T

任务是计算从0到M的自然数之和。我使用SWI Prolog编写了以下代码:

my_sum(From, To, _) :- From > To, !.
my_sum(From, To, S) :-
  From = 0,
  Next is 1,
  S is 1,
  my_sum(Next, To, S).
my_sum(From, To, S) :-
  From > 0,
  Next is From + 1,
  S is S + Next,
  my_sum(Next, To, S).
但当我试图计算时:

my_sum(0,10,S), writeln(S).

我得到的是假的而不是正确的数字。这个例子出了什么问题?

对于Next\=0,这肯定是错误的:
S是S+Next
。另一个更基本的问题是,计算是以“相反”的顺序进行的。也就是说,当
From>到
并且程序停止时,您不会“返回”结果。然后您应该添加一个累加器(另一个参数,将被传播到所有递归调用),并在最后一步将其和部分和统一起来

无论如何,应该更简单:

my_sum(From, To, S) :-
  From < To,
  Next is From + 1,
  my_sum(Next, To, T),
  S is T + From.
my_sum(N, N, N).

| ?- my_sum(2, 4, N).
N = 9
my_sum(从,到,S):-
从<到,
接下来是从+1开始,
我的金额(下一个,To,T),
S是T+From。
我的求和(N,N,N)。
|?-我的总和(2,4,N)。
N=9

对于Next\=0,这肯定是错误的:
S是S+Next
。另一个更基本的问题是,计算是以“相反”的顺序进行的。也就是说,当
From>到
并且程序停止时,您不会“返回”结果。然后您应该添加一个累加器(另一个参数,将被传播到所有递归调用),并在最后一步将其和部分和统一起来

无论如何,应该更简单:

my_sum(From, To, S) :-
  From < To,
  Next is From + 1,
  my_sum(Next, To, T),
  S is T + From.
my_sum(N, N, N).

| ?- my_sum(2, 4, N).
N = 9
my_sum(从,到,S):-
从<到,
接下来是从+1开始,
我的金额(下一个,To,T),
S是T+From。
我的求和(N,N,N)。
|?-我的总和(2,4,N)。
N=9

我将使用带有附加累加器的worker谓词,沿着这些行编写谓词:

sum(X,Y,Z) :-
  integer(X)   ,
  integer(Y)   ,
  sum(X,Y,0,Z)
  .

sum(X,X,T,Z) :- Z is T+X .
sum(X,Y,T,Z) :- X < Y , X1 is X+1 , T1 is T+X , sum(X1,Y,T1,Z) .
sum(X,Y,T,Z) :- X > Y , X1 is X-1 , T1 is T+X , sum(X1,Y,T1,Z) .
sum(X,Y,Z):-
整数(X),
整数(Y),
总和(X,Y,0,Z)
.
和(X,X,T,Z):-Z是T+X。
和(X,Y,T,Z):-XY,X1是X-1,T1是T+X,和(X1,Y,T1,Z)。

这个实现是简单的、双向的,这意味着
sum(1,3,X)
sum(3,1,X)
都会产生6个结果(1+2+3),并且尾部递归,这意味着它应该能够处理任何大小的范围而不会出现堆栈溢出。

我将沿着这些行编写谓词,将辅助谓词与附加累加器一起使用:

sum(X,Y,Z) :-
  integer(X)   ,
  integer(Y)   ,
  sum(X,Y,0,Z)
  .

sum(X,X,T,Z) :- Z is T+X .
sum(X,Y,T,Z) :- X < Y , X1 is X+1 , T1 is T+X , sum(X1,Y,T1,Z) .
sum(X,Y,T,Z) :- X > Y , X1 is X-1 , T1 is T+X , sum(X1,Y,T1,Z) .
sum(X,Y,Z):-
整数(X),
整数(Y),
总和(X,Y,0,Z)
.
和(X,X,T,Z):-Z是T+X。
和(X,Y,T,Z):-XY,X1是X-1,T1是T+X,和(X1,Y,T1,Z)。

这个实现是简单的,双向的,这意味着
sum(1,3,X)
sum(3,1,X)
都会产生6个结果(1+2+3),并且尾部递归,这意味着它应该能够处理任何大小的范围而不会出现堆栈溢出。

事实上,还有一个纯粹的解析解:

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

?- sum(100, N).
N = 5050.

您使用了循环标记,因此这可能不是您想要的答案,但如果存在这种解决方案,最好选择这种解决方案。

事实上,还有一种纯粹的分析解决方案:

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

clauses
 sum(0,0).
 sum(N,R):-
     N1=N-1,
     sum(N1,R1),
     R=R1+N.
使用中:

?- sum(100, N).
N = 5050.


您使用了循环标记,因此这可能不是您想要的答案,但如果存在这种解决方案,最好选择这种解决方案。

my_sum(From,to,u):-From>to
表示如果
From
大于
To
并提供未定义的结果,则成功。这就是你想要的吗?
my_sum(From,To,To):-From>To
表示如果
From
大于
To
并提供未定义的结果,则成功。这就是你想要的吗?请,你能解释为什么S是S+下一个结果为False吗?Prolog中的变量是不可修改的:只能是自由的或绑定到一个值。那么对S的求值为S+N肯定会失败,因为N\=0谢谢!我想我开始明白了。)@AndrejKirejeŭ-为了详细说明Capelical的评论,Prolog中的“变量”与大多数其他语言中的变量不同。它们不是可自由分配的。在Prolog中,一个变量被语言“实例化”以试图使某件事情成功,一旦实例化,它就不能被重新实例化,除非通过回溯。为什么你建议非TR解决方案?(我只是不能上传非TR代码)。请您解释一下为什么S是S+下一个结果为False?Prolog中的变量是不可修改的:只能是自由的或绑定到一个值。那么对S的求值为S+N肯定会失败,因为N\=0谢谢!我想我开始明白了。)@AndrejKirejeŭ-为了详细说明Capelical的评论,Prolog中的“变量”与大多数其他语言中的变量不同。它们不是可自由分配的。在Prolog中,一个变量被语言“实例化”以试图使某件事情成功,一旦实例化,它就不能被重新实例化,除非通过回溯。为什么你建议非TR解决方案?(我只是无法对非TR代码进行表决)。计算
sum$take 200$drop 176$cycle[1,7..242]
怎么样,我们也能轻松地得出一个封闭的解决方案吗?(请原谅Haskell语法)。:)这不是批评或任何东西,只是一个评论,:)也许是毫无意义的。计算一下
sum$take 200$drop 176$cycle[1,7..242]
,我们能很容易地得出一个封闭的解决方案吗?(请原谅Haskell语法)。:)这不是批评或什么,只是评论,:)也许是毫无意义的。谢谢你的回答!但请花几分钟时间阅读,以获得一些关于回答问题的有用提示。特别是“解释越充分越好”部分。意思:请解释为什么这回答了这个问题(比现有的答案更好)。非常感谢你的建议。这是在期望你能用它做点什么的情况下给出的。谢谢你的回答!但请花几分钟时间阅读,以获得一些关于回答问题的有用提示。特别是“解释越充分越好”部分。意思:请解释为什么这个答案(比现有答案更好)。非常感谢你的建议。它是在期望你能用它做点什么的情况下给出的。
predicates
 sum(integer,integer)

clauses
 sum(0,0).
 sum(N,R):-
     N1=N-1,
     sum(N1,R1),
     R=R1+N.