我正在尝试解码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.
你有几个错误。你从";字节";在[-128127]的范围内。我将其移动到[0255]范围以应用二进制运算。你还得到了一些偏移1,有效位的计算是错误的(忘记了隐含的1,使分数成为实际分数(
您可以很容易地增强处理非正规数的过程。您还需要注意标准提供的的各种特殊值