Оказывается, это частая ошибка. Вы должны заключать свои выражения в скобки из-за приоритета операторов.
Это то, что у вас есть:
lgstarcompute(N2,Iterations1) :- N3 is floor(log10(N2)/log10(2)), write(N2), write(N3),
N3=<1 -> Iterations1 = 1;
lgstarcompute(N3,Iterations2),
Iterations1 is Iterations2+1.
Если я отформатирую это немного лучше, я получу:
lgstarcompute(N2, Iterations1) :-
N3 is floor(log10(N2)/log10(2)),
write(N2), write(N3),
N3 =< 1 -> Iterations1 = 1
;
lgstarcompute(N3, Iterations2),
Iterations1 is Iterations2+1.
В Prolog, по крайней мере в SWI Prolog, ,
имеет более высокий приоритет, чем ->
, который выше, чем ;
. Таким образом, это эквивалентно:
lgstarcompute(N2, Iterations1) :-
(
(
N3 is floor(log10(N2)/log10(2)),
write(N2), write(N3),
N3 =< 1
) -> Iterations1 = 1
)
;
(
lgstarcompute(N3, Iterations2),
Iterations1 is Iterations2+1.
).
Что происходит, так это то, что когда N3 =< 1
терпит неудачу, Prolog возвращается назад до того, как происходит N3 is floor(...)
, чтобы достичь самой последней точки выбора, а N3
- нет. более длинный экземпляр. Затем он переходит к первому запросу после ;
, который равен lgstarcompute(N3, Iterations2)
с N3
неустановленным.
Чтобы исправить это, вам нужно сгруппировать его, используя круглые скобки:
lgstarcompute(N2, Iterations1) :-
N3 is floor(log10(N2)/log10(2)),
write(N2), write(N3),
( N3 =< 1
-> Iterations1 = 1
; lgstarcompute(N3, Iterations2),
Iterations1 is Iterations2+1
).
Теперь когда N3 =< 1
терпит неудачу, он не будет возвращаться к write(N3)
и полностью вернуться к N3 is floor(...)
, а скорее примет соединение с N3
, все еще созданным.