Давайте рассмотрим определение предиката шаг за шагом.Сначала у вас есть факт ...
power(X,0,1).
..., который гласит: 0-я степень любого X
равна 1
.Тогда есть факт ...
power(X,1,X).
..., который гласит: 1-я сила любой X
равна X
сам по себе. Наконец, у вас есть рекурсивное правило, которое гласит:
power(X,N,P) :- % P is the Nth power of X if
N1 is N-1, % N1 = N-1 and
power(X,N1,P1), % P1 is the N1th power of X and
P is P1*X. % P = P1*X
Возможно, ваша путаница связана с двумя базовыми случаями, которые выражены двумя фактами (один из них на самом деле является излишним).Давайте рассмотрим следующие запросы:
?- power(5,0,X).
X = 1 ;
ERROR: Out of local stack
Ответ 1
- это, конечно, то, что мы ожидаем, но затем предикат зацикливается, пока он не исчерпает стек.Это, конечно, не желательно.И этот запрос ...
?- power(5,1,X).
X = 5 ;
X = 5 ;
ERROR: Out of local stack
... дважды дает правильный ответ, прежде чем закончится стек.Причина избыточного ответа состоит в том, что рекурсивное правило может уменьшить любое заданное значение N
до нуля и до единицы, что дает один и тот же ответ дважды.Если вы посмотрите на структуру вашего рекурсивного правила, очевидно, что первого базового случая достаточно, поэтому давайте удалим второй.Причина выхода из стека заключается в том, что после того, как N
станет нулевым, рекурсивное правило будет искать другие решения (для N=-1
, N=-2
, N=-3
, ...), которые не существуют.Чтобы избежать этого, вы можете добавить цель, которая препятствует дальнейшему поиску рекурсивного правила, если N
равно или меньше нуля.Это оставляет вам следующее определение:
power(X,0,1). % the 0th power of any X is 1
power(X,N,P) :- % P is the Nth power of X if
N > 0, % N > 0 and
N1 is N-1, % N1 = N-1 and
power(X,N1,P1), % P1 is the N1th power of X and
P is P1*X. % P = P1*X
Теперь предикат работает, как и ожидалось:
?- power(5,0,X).
X = 1 ;
false.
?- power(5,1,X).
X = 5 ;
false.
?- power(5,3,X).
X = 125 ;
false.
Надеюсь, это ослабит некоторые ваши заблуждения.