В оригинале, binary_number([], _, N, N).
, то _
означает, что вы не все равно, что значение переменной. Если вы использовали, binary_number([], X, N, N).
(не заботясь о том, что такое X
), Prolog выдаст предупреждение о одиночной переменной. Кроме того, что говорится в этом предложении предиката: когда первый аргумент равен []
(пустой список), то третий и четвертый аргументы унифицированы.
Как поясняется в комментариях, use_module(library(clpfd))
заставляет Prolog использовать библиотеку для Программирование логики Constraint по конечным областям. Вы также можете найти много полезной информации об этом через поиск Google «proog clpfd».
Обычно в Прологе, арифметические выражения сравнения требует, чтобы выражения полностью инстанцированы:
X + Y =:= Z + 2. % Requires X, Y, and Z to be instantiated
Пролог будет оценивать и делать сравнение и выход истинным или ложным. Он выдавал бы ошибку, если бы какая-либо из этих переменных не была создана. Кроме того, для присвоения, то is/2
предиката требует, чтобы выражение правой руки полностью с конкретным анализом переменных все экземплярами:
Z is X + Y. % Requires X and Y to be instantiated
Использованием CLPFD вы можете иметь решение Пролога «исследовать» для вас. И вы также можете указать, в какой области вы хотите ограничить переменные. Итак, вы можете сказать X + Y #= Z + 2
, и Prolog может перечислять возможные решения в X
, Y
и Z
.
Как и в сторону, оригинальная реализация может быть переработан немного, чтобы избежать экспоненциация каждый раз и устранить reverse
:
:- use_module(library(clpfd)).
binary_number(Bin, N) :-
binary_number(Bin, 0, N).
binary_number([], N, N).
binary_number([Bit|Bits], Acc, N) :-
Bit in 0..1,
Acc1 #= Acc*2 + Bit,
binary_number(Bits, Acc1, N).
Это хорошо работает для запросов, таких как:
| ?- binary_number([1,0,1,0], N).
N = 10 ? ;
no
| ?- binary_number(B, 10).
B = [1,0,1,0] ? ;
B = [0,1,0,1,0] ? ;
B = [0,0,1,0,1,0] ? ;
...
Но, как отмечалось в комментариях, у него есть проблемы с завершением, например, Bs = [1|_], N #=< 5, binary_number(Bs, N).
A solution was presented by @false, который просто модифицирует приведенное выше, помогает решить эти проблемы с окончанием. Я буду повторять это решение для удобства:
:- use_module(library(clpfd)).
binary_number(Bits, N) :-
binary_number_min(Bits, 0,N, N).
binary_number_min([], N,N, _M).
binary_number_min([Bit|Bits], N0,N, M) :-
Bit in 0..1,
N1 #= N0*2 + Bit,
M #>= N1,
binary_number_min(Bits, N1,N, M).
Попробуйте 'binary_number ([1,0,0], N)', чтобы увидеть, что требуется 'reverse/2'.Для 'library (clpfd)' смотрите [tag: clpfd]. Есть более простые примеры. 'factorial/2' - хорошее начало. – false
1? - binary_number ([1,0,1,1,0,0,1], L). L = 77. Я сделал это, поэтому я не понимаю, в чем его польза. –
Почему вы смотрите на более сложные запросы? Посмотрите на более простые. – false