消息:1031序言中的算术溢出

时间:2018-12-01 21:13:20

标签: prolog

谓词

nondeterm s(integer,integer)  
nondeterm p(integer,integer,integer)  

条款

s(V,R) :-
    p(0,V,R).

%,write(R),nl.

p(R,0,R).

p(Inc,V,R) :-
    I2=Inc+V,
    N1=V-1,
    p(I2,N1,R).

目标

s(9,O).

给出算术溢出,为什么?

2 个答案:

答案 0 :(得分:2)

在Prolog中,数学表达式不是通过赋值完成的,例如=。 Prolog不像许多常见的编程语言那样使用赋值,Prolog使用统一。如果要在Prolog中进行数学表达式并用变量统一结果,则需要使用is / 2运算符

I2 is Inc+V
N1 is V-1

如果第二个参数为0,您还需要一条保护语句以防止第二个子句被执行。

s(V,O) :-
    p(0,V,O).

p(R,0,R).

p(Inc,V,R) :-
    V \= 0,
    I2 is Inc+V,
    N1 is V-1,
    p(I2,N1,R).

现在您的查询返回

?- s(9,O).
O = 45 ;
false.

答案 1 :(得分:0)

作为盖伊的答案的补充,在Prolog跟踪器中运行查询非常有帮助,因为它清楚地表明,因为您使用统一(=/2)而不是算术表达式求值(is/2),所以查询在每次递归调用时建立一个越来越大的复合项,直到耗尽全局堆栈空间为止:

[trace]  ?- s(9,O).
   Call: (8) s(9, _3176) ? creep
   Call: (9) p(0, 9, _3176) ? creep
   Call: (10) _3396=0+9 ? creep
   Exit: (10) 0+9=0+9 ? creep
   Call: (10) _3402=9-1 ? creep
   Exit: (10) 9-1=9-1 ? creep
   Call: (10) p(0+9, 9-1, _3176) ? creep
   Call: (11) _3408=0+9+(9-1) ? creep
   Exit: (11) 0+9+(9-1)=0+9+(9-1) ? creep
   Call: (11) _3414=9-1-1 ? creep
   Exit: (11) 9-1-1=9-1-1 ? creep
   Call: (11) p(0+9+(9-1), 9-1-1, _3176) ? creep
   Call: (12) _3420=0+9+(9-1)+(9-1-1) ? creep
   Exit: (12) 0+9+(9-1)+(9-1-1)=0+9+(9-1)+(9-1-1) ? creep
   Call: (12) _3426=9-1-1-1 ?
   ...