将二进制转换为十进制谓词

Convert Binary to decimal predicate

convertBinToDec(B,D):- atom_number(S,B),
                       atom_length(S,L),
                       sub_atom(S, 0, 1, After,S1),
                       atom_number(S1,N),
                       L1 is L-1,
                       sub_atom(S, 1,L1, After ,S2),
                       atom_number(S2,B2),
                       convertBinToDec(B2,D1),
                       D is D1+((2*N)**L1).
convertBinToDec(0,0).
convertBinToDec(1,1).

谓词采用 B,它是整数形式的二进制数,应该 return D 其对应的十进制形式,抱歉,我对声明性编程语言还是陌生的,但我不知道为什么我上面的代码总是给假,我觉得基本情况有问题也不允许使用序言库

您已使用After两次。子句中变量的任何使用都可以实例化为一个单一的值。 After 不能在对过程 sub_atom 的两次调用中采用两个不同的值。这会奏效,请尝试找出原因?

convertBinToDec(B,D):- atom_number(S,B),
                       atom_length(S,L),
                       sub_atom(S, 0, 1, After,S1),
                       atom_number(S1,N),
                       sub_atom(S, 1, After, 0, S2),
                       atom_number(S2, B2),
                       convertBinToDec(B2,D1),
                       D is D1+((2*N)**(L-1)).
convertBinToDec(0,0).
convertBinToDec(1,1).

这是高度程序化的思维。

一个更惯用的序言解决方案是

conv([], 0).
conv([0|Xs], N) :-
    conv(Xs, N).
conv([1|Xs], N) :-
    conv(Xs, N1),
    length(Xs, L),
    N is 2**L + N1.

% To convert atoms to binary list
code_to_binary(48, 0).
code_to_binary(49, 1).

convAtom(B, D) :-
    atom_codes(B, C),
    maplist(code_to_binary, C, Bin),
    conv(Bin, D).

conv/2 完成大部分计算。分区数据表示和问题的核心逻辑总是一个好主意。

示例:

?- conv([1, 0, 0, 1], X).
X = 9.

?- conv([0, 0, 1, 0 , 0, 0, 1], X).
X = 17

?- convAtom('1010', X).
X = 10.

?- convAtom('0010001', X).
X = 17.

鉴于 Prolog 支持使用 0b 前缀表示二进制数,例如0b10011101,可以使用标准的number_codes/2谓词进行转换:

convert_binary_to_decimal(Binary, Decimal) :-
    number_codes(Binary, Codes),
    number_codes(Decimal, [0'0, 0'b| Codes]).

调用示例:

| ?- convert_binary_to_decimal(10011101, Decimal).

Decimal = 157

yes

验证结果:

| ?- Decimal is 0b10011101.

Decimal = 157

yes