首先,您的第二个子句是非尾递归的(您可以阅读主题here)。这意味着最终,您将在运行时耗尽调用堆栈内存。
一件好事是使用累加器使其尾递归。您可以按如下方式实现:
% we add an accumulator to poW/3, making it pow/4.
pow(B, E, Result) :- pow(B, E, 1, Result).
% when we hit 0, our accumulator holds B^E so we unify it with result.
pow(_, 0, Accu, Accu) :- !.
% at each step, we multiply our accumulator by B
pow(B, E, Accu, Result) :-
NewE is E - 1,
NewAccu is Accu * B,
pow(B, NewE, NewAccu, Result).
然后,您可以通过将此子句添加到其他子句来简单地处理否定情况(它只是告诉 prolog 负幂是正幂的倒数):
pow(B, E, Result) :-
E < 0,
PositiveE is - E,
pow(B, PositiveE, 1, R),
!,
Result is 1 / R.
请注意,您可以直接使用您的代码:
pow(B, E, Result) :-
E < 0,
PositiveE is - E,
pow(B, PositiveE, R),
!,
Result is 1 / R.
另外,我们现在引入了一个非常红色的切割(如有必要,请参阅here 了解红色切割的含义)。所以最好通过这个修改变成绿色切割:
pow(B, E, Result) :-
E < 0,
PositiveE is - E,
pow(B, PositiveE, 1, R),
!,
Result is 1 / R.
% we add an accumulator to poW/3, making it pow/4.
pow(B, E, Result) :-
E >= 0, %************* HERE *****************
pow(B, E, 1, Result).
% when we hit 0, our accumulator holds B^E so we unify it with result.
pow(_, 0, Accu, Accu) :- !.
% at each step, we multiply our accumulator by B
pow(B, E, Accu, Result) :-
NewE is E - 1,
NewAccu is Accu * B,
pow(B, NewE, NewAccu, Result).