我需要写一个谓词eval(P,A,R),其中:
P表示多项式系数的列表,即1 + 2x + 3x ^ 2表示为[1,2,3]
A代表X的值
R是X = A处的多项式的结果。
例子: eval([3,1,2],3,R)产生R = 24. *编辑,以前不正确的例子
我正试图在Learn Prolog Now上使用本文和示例中的累加器。
我的算法:
0.将结果和指数变量初始化为0
1.取名单的头部
2.将列表的头部乘以A ^(指数)
3.更新结果和指数。
我的代码:
eval(P,A,R) :- accEval(P,A,0,0,R).
accEval(([H|T]),A,Pow,Accres,R) :-
Rnew is (Accres+H*(A**Pow)),
Pownew is Pow+1,
R = Accres,
accEval(T,A,Pownew,Rnew,Rnew). % *See below
accEval([],A,Pow,Accres,Accres).
% *Previously, when the second Rnew in this line was R instead, output was "no".
生成跟踪:
| ?- eval([1,2],3,R).
1 1 Call: eval([1,2],3,_20) ?
2 2 Call: accEval([1,2],3,0,0,_20) ?
3 3 Call: _126 is 0+1*3**0 ?
3 3 Exit: 1.0 is 0+1*3**0 ?
4 3 Call: _157 is 0+1 ?
4 3 Exit: 1 is 0+1 ?
5 3 Call: accEval([2],3,1,1.0,1.0) ?
6 4 Call: _218 is 1.0+2*3**1 ?
6 4 Exit: 7.0 is 1.0+2*3**1 ?
7 4 Call: _249 is 1+1 ?
7 4 Exit: 2 is 1+1 ?
8 4 Call: accEval([],3,2,7.0,7.0) ?
8 4 Exit: accEval([],3,2,7.0,7.0) ? % We have the correct answer.
5 3 Exit: accEval([2],3,1,1.0,1.0) ? % Wait! What are you doing!?
2 2 Exit: accEval([1,2],3,0,0,0) ? % Why is this falling back out?
1 1 Exit: eval([1,2],3,0) ?
R = 0 % Incorrect. The answer should be 7.
正如我的代码所述,先前的尝试没有为R产生任何价值,而是产生“否”或在其他实施中产生“是”。
为什么结果丢失而没有带回原来的电话?
答案 0 :(得分:2)
它有点简单:
eval(P,A,R) :- accEval(P,A,0,0,R).
accEval(([H|T]),A,Pow,Accres,R) :-
Rnew is (Accres+H*(A**Pow)),
Pownew is Pow+1,
accEval(T,A,Pownew,Rnew,R). % *See below
accEval([],_A,_Pow,Accres,Accres).
但您的示例似乎不正确
?- eval([3,2,1],3,R).
R = 18.
并且实际上3 + 2 * X + X ^ 2,其中X = 3,产生18 p
答案 1 :(得分:1)
应该在递归结束时与累加器值统一的变量已经绑定到一个值。使用累加器的方式如下:
根据经验,谓词头部的Result变量是传递给递归调用的相同变量。这样,一旦它与最后的实际结果统一(在递归结束子句中),它也将被递送出递归到调用者。
答案 2 :(得分:0)
这里的策略可能是所谓的Horner架构。在Horner模式中,您不需要幂函数(**)/ 2或(^)/ 2。 Horner schema说:
a_0 + a_1*x + .. + a_n-1*x^n-1 + a_n*x^n =
a_0 + x*(a_1 + .. + x*(a_n-1 + x*a_n)..)
如果允许以相反的顺序[a_n,..,a_0]提供系数,Horner模式很容易在Prolog中实现,如下所示:
eval([C|L], X, R) :-
eval(L, C, X, R).
eval([C|L], A, X, R) :-
B is A*X+C,
eval(L, B, X, R).
eval([], A, _, A).
作为奖励,霍纳计划在数值上更加稳定。以下是一个示例运行:
?- eval([2,1,3],3,R).
R = 24