Binary 二进制到十进制-prolog

Binary 二进制到十进制-prolog,binary,prolog,decimal,clpfd,Binary,Prolog,Decimal,Clpfd,我在stack上找到了这个: 但我不明白 :- use_module(library(clpfd)). binary_number(Bs0, N) :- reverse(Bs0, Bs), binary_number(Bs, 0, 0, N). binary_number([], _, N, N). binary_number([B|Bs], I0, N0, N) :- B in 0..1, N1 #= N0 + (2^I0)*

我在stack上找到了这个:

但我不明白

:- use_module(library(clpfd)).

binary_number(Bs0, N) :-
        reverse(Bs0, Bs),
        binary_number(Bs, 0, 0, N).

binary_number([], _, N, N).
binary_number([B|Bs], I0, N0, N) :-
        B in 0..1,
        N1 #= N0 + (2^I0)*B,
        I1 #= I0 + 1,
        binary_number(Bs, I1, N1, N).
示例查询:

?- binary_number([1,0,1], N).
N = 5.

?- binary_number(Bs, 5).
Bs = [1, 0, 1] .
谁能给我解释一下密码吗

特别是:
二进制数([],N,N,N)。
(二进制数)

图书馆(clpfd)也做什么

为什么要反向(Bs0,Bs)?我把它拿走了它还可以用


thx预先

在原始的二进制数([],[uu,N,N)。中,
\uu
表示您不关心变量的值。如果使用,
binary_number([],X,N,N)。
(不管
X
是什么),Prolog将发出单例变量警告。同样,这个谓词子句所说的是,当第一个参数是
[]
(空列表)时,第三个和第四个参数是统一的

如注释中所述,
use_module(library(clpfd))
使Prolog使用该库进行有限域上的约束逻辑编程。你也可以通过谷歌搜索“prolog clpfd”找到很多关于它的好信息

通常,在Prolog中,比较的算术表达式要求表达式完全实例化:

X + Y =:= Z + 2.  % Requires X, Y, and Z to be instantiated
Z is X + Y.  % Requires X and Y to be instantiated
Prolog将进行评估和比较,并得出正确或错误的结果。如果没有实例化这些变量中的任何一个,它将抛出一个错误。同样,对于赋值,
is/2
谓词要求右侧表达式完全可计算,且所有特定变量均实例化:

X + Y =:= Z + 2.  % Requires X, Y, and Z to be instantiated
Z is X + Y.  % Requires X and Y to be instantiated
使用CLPFD,您可以使用Prolog“探索”解决方案。您还可以进一步指定要将变量限制在哪个域。因此,您可以说
X+Y#=Z+2
,Prolog可以在
X
Y
Z
中列举可能的解决方案

另一方面,可以对原始实现进行一些重构,以避免每次的求幂运算,并消除
反向

:- 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,二进制数(Bs,N)。
A简单地修改上述内容有助于解决这些终止问题。为了方便起见,我在此重申该解决方案:

:- 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).

尝试
二进制数([1,0,0],N)
查看是否需要
反向/2
。有关
库(clpfd)
请查看。还有更简单的例子<代码>阶乘/2是一个好的开始。1?-二进制_数([1,0,1,1,0,0,1],L)。L=77。我之所以这么做,是因为我不明白它有什么用。为什么要看更复杂的查询?看看更简单的,我需要把二进制转换成十进制。我发现了这个,所以我试着去理解。简单的阶乘运算我知道怎么做。另外一个更好的方法是努力尝试你不理解clpfd中的
factorial/2
示例的东西。毕竟,你是在问“库(clpfd)做什么?”你不会问这个问题,你会在这里学习并理解
factorial/2
吗。你应该是一名教师:)很多终止问题。看@false Thank,我会认真研究的。我在这里的编辑是为了采用我之前发布的一个笨重的解决方案,它也有类似的终止问题,并使它不那么笨重。但你是对的:终止合同的问题仍然存在。