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

Decoding raw bytes received by udp_receive with as( codes )

我正在尝试自己解码 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.

您有一些错误。您从 [-128, 127] 范围内的“字节”开始。我将它移动到范围 [0,255] 以应用二元运算。 你也有一些偏移 1,有效数的计算是错误的(忘记了隐含的 1 并使分数成为实际分数)

您可以轻松增强处理非正规数的程序。您还需要注意标准提供的各种特殊值