1

我是序言的新手。我正在做一个递归程序,问题是即使它打印了答案..它在打印答案后并没有停止并最终给出“超出本地堆栈”。我已经读过它可能是一个左递归问题,但正如我已经告诉过你的那样,我是 prolog 的新手,我真的不明白会发生什么......所以......这里的代码。

f(X, Y):-
    Y is sqrt(1-((X-1)*(X-1))).

sum(SEGMENTS, 1, TOTAL):-
    f(2/SEGMENTS*1,H1),
    TOTAL is (2/SEGMENTS)*H1.

sum(SEGMENTS, NR, TOTAL):-
    N1 is (NR-1),
    sum(SEGMENTS, N1, S1),
    f(2/SEGMENTS*NR,H1),
    f(2/SEGMENTS*N1,H2),
    TOTAL is S1 + (2/SEGMENTS)*((H1+H2)/2).

它应该用梯形规则或类似的东西计算一个半圆的面积。正如我已经告诉过你的那样..它确实完成了,但是在达到基本情况 sum(segments, 1, total) 之后,它使用第二种选择调用函数......:S

多谢你们!

另外:这是我运行它时得到的

?- sum(3000,3000,TOTAL).
TOTAL = 1.5707983753431007 ;
ERROR: Out of local stack
4

1 回答 1

2

问题是回溯将在第一个子句成功后尝试第二个子句的NRvalue 的情况。这会导致一个长的递归过程(因为 NR 对于每个递归调用都在不断递减,尝试遍历所有负整数值等)。1sum

解决问题的一个简单方法是在您的第二sum个子句中。由于意图是针对 的情况NR > 1,因此将NR > 1其作为您的第一条语句:

sum(SEGMENTS, NR, TOTAL) :-
    NR > 1,
    N1 is (NR-1),
    sum(SEGMENTS, N1, S1),
    f(2/SEGMENTS*NR,H1),
    f(2/SEGMENTS*N1,H2),
    TOTAL is S1 + (2/SEGMENTS)*((H1+H2)/2).

另请注意,表达式f(2/SEGMENTS*NR, H1)不会计算表达式2/SEGMENTS*NR并将其传递给f. 它实际上象征性地传递了该表达式。它恰好在这里起作用,因为f它包含在 an 的右侧,is/2因此可以根据需要对其进行评估。如果你追踪它,你就会明白我的意思。

于 2013-11-04T11:47:11.343 回答