使用as(codes)解码udp_receive接收到的原始字节



我正在尝试解码udp_received接收的原始字节列表。

两个问题:

  1. 我还没有找到任何标准的方法,比如Java 中的ByteBuffer

  2. decodeDouble中存在错误,而decodeLong工作正常。

最好使用标准。

对字节列表进行操作对于集成已经构建的用C/C++和Java开发的系统是强制性的。

这是代码:

decodeLong( [B0,B1,B2,B3,B4,B5,B6,B7|Remaining], Long, Remaining ) :-
Long is (B0 << 56)
/    (B1 << 48)
/    (B2 << 40)
/    (B3 << 32)
/    (B4 << 24)
/    (B5 << 16)
/    (B6 <<  8)
/    (B7 <<  0).
decodeDouble( [B0,B1,B2,B3,B4,B5,B6,B7|Remaining], Double, Remaining ) :-
((B0 >> 7) > 0 -> Sign = -1 ; Sign = +1),
Fraction is ((B1 / 0x0F) << 48)
/        ( B2          << 40)
/        ( B3          << 32)
/        ( B4          << 24)
/        ( B5          << 16)
/        ( B6          <<  8)
/        ( B7          <<  0),
Exponent is ((B0 / 0x7F) / ((B1 / 0xE0) >> 5)),
ExponentBias is 2^( 11 - 1) - 1, % double: 11 bits for Exponent
format( "Sign    : ~w~n", [Sign]),
format( "Fraction: ~w~n", [Fraction]),
format( "Exponent: ~w~n", [Exponent]),
Double is Sign*Fraction*2^(Exponent-ExponentBias). % see IEEE 754
test :-
RawBytes = [-1, -1, -1, -1, -1, -1, -1, -123, -64, 94, -36, -52, -52, -52, -52, -51],
decodeLong( RawBytes, Long, Remaining0 ),
format( "decodeLong produces: ~w, Remaining: ~w~n", [Long, Remaining0]),
Long      = -123,
decodeDouble( Remaining0, Double, Remaining1 ),
format( "decodeDouble produces: ~w, Remaining: ~w~n", [Double, Remaining1]),
Double     = -123.45,
Remaining1 = []. % all bytes has been consumed

执行:

?- test.
decodeLong produces: -123, Remaining: [-64,94,-36,-52,-52,-52,-52,-51]
Sign    : 1
Fraction: -51
Exponent: 66
decodeDouble produces: -4.186627537324344e-287, Remaining: []
false.

我相信您最好使用本机代码来完成从字节到双字节的转换。

在其他情况下,你必须注意一些边缘情况,在这里重新发明轮子没有多大意义。

如果你仍然想写浮点数的解码器,那么你应该阅读标准或一些页面,其中包含IEEE754的信息,以添加非正规数和其他特殊值的解码。

以下是您的解码代码的修复程序。在这一点上,它只对正常数字有效(就像你的例子(:

decodeDouble( [B0,B1,B2,B3,B4,B5,B6,B7|Remaining], Double, Remaining ) :-
((B0 mod 256 >> 7) > 0 -> Sign = -1 ; Sign = +1),
Fraction is ((B1 / 0x0F) mod 256 << 48)
/        ( B2 mod 256         << 40)
/        ( B3 mod 256         << 32)
/        ( B4 mod 256         << 24)
/        ( B5 mod 256         << 16)
/        ( B6 mod 256         <<  8)
/        ( B7 mod 256         <<  0),
Significand is 1.0 + Fraction / 2^52,
Exponent is (((B0 / 0x7F mod 256) << 4) / ((B1 / 0xF0 mod 256) >> 4)),
ExponentBias is 2^( 11 - 1) - 1, % double: 11 bits for Exponent
format( "Sign    : ~w~n", [Sign]),
format( "Fraction: ~w~n", [Fraction]),
format( "Significand: ~w~n", [Significand]),
format( "Exponent: ~w~n", [Exponent]),
Double is Sign*Significand*2^(Exponent-ExponentBias). % see IEEE 754

试运行:

?- test.
decodeLong produces: -123, Remaining: [-64,94,-36,-52,-52,-52,-52,-51]
Sign    : -1
Fraction: 4183421841362125
Significand: 1.92890625
Exponent: 1029
decodeDouble produces: -123.45, Remaining: []
true.

你有几个错误。你从";字节";在[-128127]的范围内。我将其移动到[0255]范围以应用二进制运算。你还得到了一些偏移1,有效位的计算是错误的(忘记了隐含的1,使分数成为实际分数(

您可以很容易地增强处理非正规数的过程。您还需要注意标准提供的的各种特殊值

最新更新