gpt4 book ai didi

prolog - 在 Prolog 中将字节列表转换为整数

转载 作者:行者123 更新时间:2023-12-02 07:22:06 25 4
gpt4 key购买 nike

我正在尝试将字节列表转换为相应的整数。我想按照文档注释的建议绑定(bind)到第二个变量。我将其作为临时 hack 打印出来。

% bytes_int(+ByteList, -IntegerRepresentation)
% converts a list of bytes to integer representation
% I accounts for bitshifting
bytes_int(BytesList, _) :-
bytes_int(BytesList, 0, 0).

bytes_int([], _, Num) :-
format('~w', Num).
bytes_int([B|Bs], I, Num) :-
B0 is B << I,
Num0 is B0 + Num,
I0 is I + 8,
bytes_int(Bs, I0, Num0).

它正在打印正确的值,但我不确定为什么它没有绑定(bind)到第二个变量以供进一步使用。我可以做哪些改进来实现这一目标?

?- bytes_int([42, 121, 56], N).
3701034

最佳答案

我想扩展一下@WillemVanOnsem 的精彩回答。这是他发布的版本:

bytes_int(BytesList, R) :-    bytes_int(BytesList, 0, 0, R).bytes_int([], _, R, R).bytes_int([H|T], S0, R0, R) :-    R1 is R0 + H << S0,    S1 is S0 + 8,    bytes_int(T, S1, R1, R).

那么,让我们尝试一些查询。一、题中提供的测试用例:

?- bytes_int([42,121,56], I).I = 3701034.

很好,很有效。那么让我们尝试一个更一般的情况,我查询三个字节,但不指定它们的值:

?- bytes_int([A,B,C], I).ERROR: Arguments are not sufficiently instantiated

不幸的是,这不起作用:低级整数运算的使用排除了这种更一般的用例。这种限制适用于所有更一般的查询,即使它们有时可能会产生解决方案:

?- bytes_int(Bs, I).Bs = [],I = 0 ;ERROR: Arguments are not sufficiently instantiated

至少第二个参数被完全实例化的更具体的情况呢:

?- bytes_int(Bs, 3701034).ERROR: Arguments are not sufficiently instantiated

不,在这种情况下谓词也不能产生任何答案。

好吧,这都是意料之中的,更多命令式倾向的程序员此时会说。你以为我们是什么? 声明式程序员?

是的。

因此,我对上面的版本进行了以下直接更改,以使其更具声明性:我将 (is)/2 替换为 (#=)/2。是的,我知道,40 年前的书不会这样做,但我们仍然这样做,看看我们会得到什么返回:

bytes_int(BytesList, R) :-    bytes_int(BytesList, 0, 0, R).bytes_int([], _, R, R).bytes_int([H|T], S0, R0, R) :-    R1 #= R0 + H << S0,    S1 #= S0 + 8,    bytes_int(T, S1, R1, R).

让我们立即从最一般的查询开始,我们只要求任何答案:

?- bytes_int(Bs, I).Bs = [],I = 0 ;Bs = [_15310],I#=_15310<<0 ;Bs = [_16050, _16056],_16086#=_16050<<0,_16086+_16118#=I,_16118#=_16056<<8 .

不错!所以我们现在得到了更多的答案。事实上,我们现在可以测试非终止:

?- bytes_int(Bs, I), false.nontermination

这个查询不会终止的事实令人安心:由于谓词应该适用于任意长度的列表,它绝不能普遍终止。

让我们再尝试几种情况:

?- bytes_int([A,B,C], I)._3674#=A<<0,_3674+_3706#=_3700,_3706#=B<<8,_3700+_3754#=I,_3754#=C<<16.

这是上面的情况:我们现在得到了所有答案的符号表示,这有时非常有用。

特别是,原始测试用例当然会作为更一般查询的特例自然地遵循:

?- bytes_int([42,121,56], I).I = 3701034.

这与以前完全一样。

所以还有一个案例需要测试:第二个参数被实例化怎么样?

?- bytes_int(Bs, 3701034).Bs = [_5164],3701034#=_5164<<0 ;Bs = [_6056, _6062],_6080#=_6056<<0,_6080+_6112#=3701034,_6112#=_6062<<8 .

这至少会产生答案。我把它留作改进这一点的练习。回想一下,到目前为止,我所做的只是简单地将 (is)/2 替换为 (#=)/2,仅此一项就已经大大增加了这个的通用性关系。根据您的 Prolog 系统,您目前可能需要导入一个库才能从这种声明式整数算法中获益。

关于prolog - 在 Prolog 中将字节列表转换为整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42862178/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com