使用 as( codes ) 解码 udp_receive 接收到的原始字节
Decoding raw bytes received by udp_receive with as( codes )
我正在尝试自己解码 udp_received
收到的原始字节列表。
两个问题:
我还没有找到任何标准的方法,比如 Java
中的 ByteBuffer
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 并使分数成为实际分数)
您可以轻松增强处理非正规数的程序。您还需要注意标准提供的各种特殊值
我正在尝试自己解码 udp_received
收到的原始字节列表。
两个问题:
我还没有找到任何标准的方法,比如 Java
中的 ByteBufferdecodeDouble
中有错误,而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 并使分数成为实际分数)
您可以轻松增强处理非正规数的程序。您还需要注意标准提供的各种特殊值