Почему это работает:
power(_,0,1) :- !.
power(X,Y,Z) :-
Y1 is Y - 1,
power(X,Y1,Z1),
Z is X * Z1.
И это дает исключение переполнения стека?
power(_,0,1) :- !.
power(X,Y,Z) :-
power(X,Y - 1,Z1),
Z is X * Z1.
Почему это работает:
power(_,0,1) :- !.
power(X,Y,Z) :-
Y1 is Y - 1,
power(X,Y1,Z1),
Z is X * Z1.
И это дает исключение переполнения стека?
power(_,0,1) :- !.
power(X,Y,Z) :-
power(X,Y - 1,Z1),
Z is X * Z1.
Потому что арифметические операции над предложениями выполняются только через оператор is
. В вашем первом примере Y1 привязан к результату вычисления Y - 1. В последнем система пытается доказать утверждение power(X, Y - 1, Z1), которое объединяется с power(X', Y', Z') привязка X' = X, Y' = Y - 1, Z' = Z. Затем это снова рекурсивно, поэтому Y'' = Y - 1 - 1 и т. д. до бесконечности, фактически никогда не выполняя вычисления.
Пролог - это в первую очередь просто унификация терминов - расчет в «общем» смысле должен запрашиваться явно.
Y - 1
, когда Y = 1
все еще Y - 1
, пока он не связан :)
- person Pierre Bourdon; 04.10.2009
Оба определения не работают должным образом.
Учитывать
?- pow(1, 1, 2).
который зацикливается для обоих определений, потому что второе предложение может применяться независимо от второго аргумента. Сокращение в первом предложении не может отменить это. Во втором предложении требуется цель Y > 0
перед рекурсивной целью. Использование (is)/2
по-прежнему является хорошей идеей для получения актуальных решений.
Лучше всего (для начинающих) начать с преемник -арифметика или clpfd и избегать prolog-cut.
См., например: Предикат Prolog - бесконечный цикл