二进制到十进制 - 序言

时间:2015-01-05 22:07:57

标签: binary prolog decimal clpfd

我在堆栈上找到了这个:reversible "binary to number" predicate

但我不明白

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

有人可以解释一下代码

特别是:binary_number([], _, N, N).(_)

库(clpfd)的作用是什么?

为什么reverse(Bs0, Bs)?我拿走它仍然可以正常工作......

事先提前

1 个答案:

答案 0 :(得分:1)

在原作binary_number([], _, N, N).中,_表示您并不关心变量的值。如果您使用binary_number([], X, N, N).(不关心X是什么),Prolog会发出单例变量警告。此外,这个谓词子句所说的是当第一个参数是[](空列表)时,第3和第4个参数是统一的。

正如评论中所解释的那样,use_module(library(clpfd))导致Prolog使用该库进行有限域上的约束逻辑编程。您还可以通过谷歌搜索" prolog clpfd"来找到很多有关它的信息。

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

X + Y =:= Z + 2.  % Requires X, Y, and Z to be instantiated

Prolog会评估并进行比较并产生真假。如果没有实例化任何这些变量,它将抛出错误。同样,对于赋值,is/2谓词要求右侧表达式可以完全计算所有实例化的特定变量:

Z is X + Y.  % Requires X and Y to be instantiated

使用CLPFD,你可以让Prolog"探索"解决方案给你。您还可以进一步指定要将变量限制为的域。因此,您可以说X + Y #= Z + 2和Prolog可以在XYZ中枚举可能的解决方案。

顺便说一下,原始实现可以稍微重构一次,以避免每次取幂,并消除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).