Пролог никогда не пользовался популярностью благодаря своим арифметическим возможностям.
Это связано с необходимостью представления «конструкторов терминов» для символьной обработки без ненужной оценки, поэтому, когда требуется фактическая арифметика, мы должны явно выделить «пробел» (переменную) для результата, вместо «передачи вниз» ' выражение. Это приводит к довольно многословному и неприятному коду.
Но используя некоторые популярные расширения, такие как CLP (FD), доступные в GProlog, а также SWI-Prolog, мы получаем гораздо лучшие результаты, которых нет на других языках: а именно, закрытие целочисленной области над обычной арифметикой операции. Например, из библиотеки SWI-Prolog CLP (FD) «двунаправленный» факториал
n_factorial(0, 1).
n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
?- n_factorial(X, 3628800).
X = 10 .
В любом случае, вот простое решение исходной проблемы, подобное тому, что вы пытались, но с использованием аккумулятора для вычисления результата. Этот простой трюк позволяет написать хвостовую рекурсивную процедуру, которая оказывается более эффективной.
sigma(Num, Result) :-
sigma(1, Num, 0, Result).
sigma(N, M, Acc, Tot) :-
( N < M, !,
( (0 is N mod 3 ; 0 is N mod 5)
-> Sum is Acc + N
; Sum is Acc
),
N1 is N + 1,
sigma(N1, M, Sum, Tot)
; Tot is Acc
).
Тест:
?- sigma(1000, X).
X = 233168 .