如何在Prolog中做“平均”?

时间:2017-06-09 00:31:25

标签: prolog

我正试图在Prolog中做一个平均谓词,但我遇到了一些问题,

它被称为平均值(N,X),其中N是数字,X是从1到N的平均值的结果。

我试图这样做,但它并不总是运作良好:

       average(1,1).
       average(N,X) :- K is N-1 ,K>1 , average(K,S1) , X is /(+(S1,N),N).
       average(N,X) :- K is N-1 ,K=:=1 , average(K,S1) , X is +(S1,N).

一些帮助?

3 个答案:

答案 0 :(得分:5)

让我们看一下1到n之和的一些平均值:

n = 1: 1/1       = 1
n = 2: (1+2)/2   = 3/2
n = 3: (1+2+3)/3 = 2
...

现在从某种意义上说,感觉1和n之间的元素并不重要,总有1/2添加。因此,我们假设(1 + ... n)/ n =(1 + n)/ 2。我们如何为一般的n证明这一点?让我们尝试归纳,即让我们说明我们可以从n = 0到n = 1进行基本步骤然后,假设我们的公式适用于任意n,我们证明公式也适用于的n + 1。

  • 基本情况:对于n = 0,我们有(1 + 1)/ 2 = 1而对于n = 1,我们有(1 + 2)/2=1.5 - 正是我们想要的。
  • 步骤案例:假设(1 + ... + n)/ n =(1 + n)/ 2。我们还需要表明(1 + ... + n +(n + 1))/(n + 1)=(1+(n + 1))/ 2。我们可以将分数分成两部分:

    (1+...+n+(n+1))/(n+1) =
    (1+...+n)/(n+1) + (n+1)/(n+1) =
    (1+...+n)/(n+1) + 1
    

    现在我们需要通过(n + 1)对除法进行一些处理,所以让我们以不同的方式写出分数:

    (1+...+n)/(n+1) + 1 =
    (1+...+n)/n * (n/(n+1)) + 1
    

    现在我们可以使用(1 + ... + n)/ n =(1 + n)/ 2的假设并简化:

    (1+...+n)/n * (n/(n+1)) + 1 =
    (1+n)/2 * (n/(n+1)) + 1 =
    n/2 + 1 =
    (n+2)/2 =
    (1 + (n+1))/2
    

    这正是我们想要的!

现在让我们制作一个程序:

avg(N,X) :- X is (1+N)/2.

它给出了预期的结果:

?- between(1,10,C), avg(C,X).
C = X, X = 1 ;
C = 2,
X = 1.5 ;
C = 3,
X = 2 ;
C = 4,
X = 2.5 ;
C = 5,
X = 3 ;
C = 6,
X = 3.5 ;
C = 7,
X = 4 ;
C = 8,
X = 4.5 ;
C = 9,
X = 5 ;
C = 10,
X = 5.5.

此外,它比原始方法更有效!

答案 1 :(得分:3)

想想你的规则......

average(1, 1).
  

平均值为1。

听起来不错。我要跳到你的第3条规则,这也很具体,但只是冗长:

average(N,X) :- K is N-1 ,K=:=1 , average(K,S1) , X is +(S1,N).
  

如果NXK为1,则N-1的平均值为K,则K的平均值为S1 XS1+NN

这可以简化很多,因为average(2, X) :- average(1, S1), X is S1 + 2. 在此规则中必然是2:

average(1, S1)

然后,因为我们知道average(2, X) :- X is 3 % X is 1 + 2 的一个结果:

average(2, 3).

然后更进一步,只是:

average(N,X) :- K is N-1 ,K>1 , average(K,S1) , X is /(+(S1,N),N).

所以你不需要你的第三条规则的所有逻辑。

现在让我们看看第二条规则,这是你最常见的情况:

N
  

如果XKN-1,1到K > 1的平均值为K,则S1的平均值为X {1}},(S1 + N)/NK > 1

N > 2或等效N的情况。它说我可以将1的平均值设为N-1,首先将平均值设为1 N,然后添加N然后除以N获得1到N的平均值。这在数学上是无效的。让我们来看一个简单的反例,其中S1 = average of 1 to 2, = (1+2)/2 = 1.5. 是3:

S = average of 1 to 3 = (S1 + 3)/3 = (1.5+3)/3 = 4.5/3 = 1.5

现在,如果我们说平均1到3是1到2的平均值加3然后除以3,我们得到:

(1+2+3)/3

但是,正确答案为S1,即6/3或仅为2。

正确的公式是什么?好吧,N-1是1到N-1的平均值, 1到N-1 /(S)的总和。如果我想从那里转到N总和为1 N / N,这是1到S1的平均值,我需要将N-1乘以N,然后加N,再除以average(N,X) :- K is N-1, K > 1 , average(K, S1), X is (S1*(N-1)+N)/N. 。换句话说,你的第二条规则应该是:

average(1, 1).
average(2, 3).
average(N, X) :- K is N-1, K > 1 , average(K, S1), X is (S1*(N-1)+N)/N.

回到1到3的简单例子,我们发现1到2的平均值是1.5。如果我们将它乘以2,然后加3,然后除以3,我们得到:((1.5 * 2)+3)/ 3 =(3 + 3)/ 3 = 6/3 = 2,这是正确的答案。

总之,您的规则变为:

K

但实际上你并不需要第二条规则。如果我们调整N的第3个规则中的条件(或者实际上只是使其成为average(1, 1). average(N, X) :- N > 1, K is N-1, average(K, S1), X is (S1*(N-1)+N)/N. 的规则,那么第3个规则和基本案例会为您处理它,这更加清晰)。所以只是:

N

顺便说一句,我认为这只是Prolog中递归的练习,因为已经存在一个简单的公式,用于从1到N*(N+1)/2(N+1)/2)的数字之和,因此对于平均值,即:BrowserWindow

答案 2 :(得分:2)

只是为了暗示好的图书馆(aggregate)如何提供帮助:

?- aggregate((sum(N),count),member(N,[4,5,6]),(S,C)),Ave is S/C.
S = 15,
C = 3,
Ave = 5.