如何计算Prolog中数字序列的总和

时间:2013-08-07 14:31:59

标签: 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, To, S).

但是当我尝试计算时:

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

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

4 个答案:

答案 0 :(得分:2)

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

无论如何,应该更简单:

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

答案 1 :(得分:2)

我在这些行中编写谓词,使用带有附加累加器的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(1,3,X)sum(3,1,X)都会产生6(1 + 2 + 3),尾递归,这意味着它应该能够处理任何大小的范围而不会出现堆栈溢出。

答案 2 :(得分:2)

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

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

使用中:

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

你使用了循环标记,所以这可能不是你想要的答案,但是当存在这种解决方案时,最好选择这种解决方案。

答案 3 :(得分:0)

class CreateProductForm(forms.Form):
    name = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
    content = forms.CharField(widget=forms.Textarea(attrs={'class':'form-control', 'id': 'ck-editor-area'}))
    excerpt = forms.CharField(widget=forms.Textarea(attrs={'class':'form-control', 'rows': '7'}), required=False)
    price = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control', 'placeholder': 'Amount'}))
    status = forms.CharField(widget=forms.Select(choices=(('1', 'Active'),('0', 'Inactive'),), attrs={'class':'form-control'}))
    quantity = forms.CharField(widget=forms.NumberInput(attrs={'class':'form-control'}))