今天diocp裙中[珠海]-芒果反应了一个关于SimpleMsgPack的问题
msgPack.AsFloat = 2.507182;
经过编码再解码后,会直接触发异常。
因为msgPack的标准,在打包的数据是大端法IEEE 754
下面是msgPack的标准说明
Float format family stores a floating point number in bytes or bytes.
float stores a floating point number in IEEE single precision floating point number format:
+--------+--------+--------+--------+--------+
| 0xca |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX
+--------+--------+--------+--------+--------+ float stores a floating point number in IEEE double precision floating point number format:
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xcb |YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
where
* XXXXXXXX_XXXXXXXX_XXXXXXXX_XXXXXXXX is a big-endian IEEE single precision floating point number
* YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY is a big-endian
IEEE double precision floating point number
小端法变大端法把自己顺序调整下就好了
在SimpleMsgPack中有一个这样的函数,可以对Double类型的数据进行交换字节数。
procedure swap64Ex(const v; out outVal);
begin
// 7F F5 B8 6F B5 0E // 0E B5 6F B8 F5 7F
PByte(@outVal)^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(IntPtr(@v) + )^;
PByte(IntPtr(@outVal) + )^ := PByte(@v)^;
end;
然后我重载了一些函数 这个函数对传入的Double进行交换字节然后返回Double类型
function swap(v:Double): Double; overload;
begin
swap64Ex(v, Result);
end;
上面这个浮点数据 2.507182,经过交换后 如果仍然用Double类型来存放会是一个NaN, 会触发一个无效的浮点型数据的异常。因为不符合小端法的IEEE规则。
经过稍微修改后正常
function swap(v:Double): Int64; overload;
begin
swap64Ex(v, Result);
end;
返回的值用Int64来存放这样就好了。
注意不要把一个不是Double类型的数据直接强制转换成Double类型,因为Double是有标准字节格式的,当然Single一样。