2012-04-16 100 views
1

我对Prolog完全陌生,并且在做家庭作业。我的程序应该采用两个等长的列表,并执行D = sqrt((X1-Y1)^ 2 +(X2-Y2)^ 2 + ... +(XN-YN)^ 2)。我已经编写了代码来获得正确的答案,但它没有正确显示。我认为这可能是逻辑流程的一个问题,因为它看起来像是在一个无限循环中结束。它应该是这样的:Prolog逻辑流程

?- distance([1,2,3], [2,3,4], D). 
D = 1.732051. 

我的代码是给我正确的结果,但它打印它想:

?- distance([1,2,3],[2,3,4],D). 
1.732051 
true 

只是因为我有一条线在那里打印的结果。它也没有结束(没有时期),直到我进入,这就是为什么我害怕我有一个循环。如何更改我的代码或重定向我的逻辑,使其正常打印?

distance([],[],D) :- 
    F is sqrt(D), 
    format("~f~n", [F]). 

distance([A|T1], [B|T2], D) :- 
    var(D), 
    S is (A-B)*(A-B), 
    distance(T1, T2, S); 
    C is A-B, 
    E is C*C, 
    F is D+E, 
    distance(T1, T2, F). 
+0

不应该'F'评价为'd-E',而不是'd + E'?你希望递归距离是总距离减去每次第一项的距离。我也对'distance(T1,T2,S)'这一行感到困惑;'你可以评论一下吗? – ely 2012-04-16 21:49:41

+0

N/M,我明白你现在在做什么..在最后一个参数中累积距离的总和。我认为这有点混乱,但是正确。所以唯一的问题是奇怪的印刷。我认为这与你缺乏真正的基础案例有关。在你的方法中,距离([],[],0)不会成立。另请注意,代码在运行时如何挂起,等待额外的'。'。返回true后。 – ely 2012-04-16 22:01:05

回答

2

你的程序没有进入死循环,否则你很可能会在某个时候出现堆栈溢出错误。 发生什么事是你的代码留下了一个开放的选择点,所以最终解释器试图重做(失败)。 您没有按预期得到结果,因为调用过程中使用的变量D永远不会被绑定。

你最好解决这个问题,思考如何递归地建模。在这种情况下,你可以例如在输入列表为空时和不在时输入列表分开问题(我在这里假设用空列表调用你的过程将产生0结果)。

因此,在这种情况下,您将创建两个子句,一个用于基本情况(空列表),另一个用于递归步骤。我还将使用一个在使用累加器组成的prolog中使用的常用方法。

所以我们创建距离/ 3事实只会调用使用该蓄电池另一个过程:

distance(L1,L2,F) :- 
    distance(L1, L2, 0, F). 

我们用蓄电池持有的平方项差之和的部分结果(AB) *(AB)在你的代码:

现在我们先从基本情况(空列表):

distance([],[],S,F) :- 
    F is sqrt(S). 

这里我们规定的时候,没有更多的项目留我是累加器的平方根。

我们现在跟随递归步骤,计算每个列表中第一项的平方项差异并进行递归。

distance([A|T1], [B|T2], D, SQRT) :- 
    S is D+(A-B)*(A-B), 
    distance(T1, T2, S, SQRT). 

现在我们正在这样做:

?- distance([1,2,3],[2,3,4],D). 
D = 1.7320508075688772. 
+0

当然!谢谢你如此清晰简洁地解释一切。我使用了你给我的修改,现在它可以工作。谢谢! – AmberWolfe 2012-04-16 22:38:16

0

我不明白,使用format功能,因此,所有我能做的就是提供这个我自己尝试。我认为你的尝试有一个缺点,就是递归的基本情况没有明确说明。

考虑下面我的做法:

distance([],[],0). 
distance([A],[A],0). 
distance([A|T1],[B|T2],D) :- 
    distance(T1,T2,F), 
    D is sqrt((A-B)*(A-B) + F*F). 
+0

请注意,您正在计算另一个功能。例如,在你要做的3个项目列表中,(A1-B1)^ 2 + sqrt((A2-B2)^ 2 + sqrt((A3-B3)^ 2)^ 2)^ 2'。你的第二个基本情况也是没有必要的。 – gusbro 2012-04-16 22:15:09

+0

第二个基本情况比没有情况快吗?也许也更强大的数字(尽管通常这在Prolog中不是问题)。 – ely 2012-04-16 22:15:40

+0

问题是它不太清楚。如果你希望它更快,也更强大,你可能应该使用累加器来允许尾递归(否则你可能会遇到栈问题) – gusbro 2012-04-16 22:17:47

0

我认为你应该使用的蓄电池:

distance(L1, L2, D) :- 
    distance(L1, L2, 0, D). 

distance([], [], TT, D) :- 
    D is sqrt(D). 

distance([X1 | Y1], [X2 | Y2], TT, D) :- 
    TT1 is TT + (X1 - X2) * X1 - X2), 
    distance(Y1, Y2, TT1, D).