可逆的"二进制到数字"谓词

Ale*_*man 9 prolog clpfd

将二进制位(例如,可能是0/1的列表)以可逆方式转换为数字的最佳方法是什么.我在swi中编写了一个原生谓词,但有更好的解决方案吗?最好的祝福

mat*_*mat 10

使用CLP(FD)约束,例如:

:- use_module(library(clpfd)).

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

binary_number_(B, I0-N0, I-N) :-
        B in 0..1,
        N #= N0 + B*2^I0,
        I #= I0 + 1.
Run Code Online (Sandbox Code Playgroud)

示例查询:

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

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

?- binary_number(Bs, N).
Bs = [],
N = 0 ;
Bs = [N],
N in 0..1 ;
etc.
Run Code Online (Sandbox Code Playgroud)


fal*_*lse 7

这是我想到的解决方案,或者更确切地说,我希望存在的解决方案.

:- use_module(library(clpfd)).

binary_number(Bs, N) :-
   binary_number_min(Bs, 0,N, N).

binary_number_min([], N,N, _M).
binary_number_min([B|Bs], N0,N, M) :-
   B in 0..1,
   N1 #= B+2*N0,
   M #>= N1,
   binary_number_min(Bs, N1,N, M).
Run Code Online (Sandbox Code Playgroud)

该解决方案也终止于以下查询:

?- Bs = [1|_], N #=< 5, binary_number(Bs, N).
Run Code Online (Sandbox Code Playgroud)

  • 这是关于终止问题(+1)的优雅,简单的方法,并避免取幂(:)). (2认同)