关于SimpleMsgPack中swap引发的问题大端法和小端法研究笔记

今天diocp裙中[珠海]-芒果反应了一个关于SimpleMsgPack的问题

msgPack.AsFloat = 2.507182;

经过编码再解码后,会直接触发异常。

因为msgPack的标准,在打包的数据是大端法IEEE 754

下面是msgPack的标准说明

Float format family stores a floating point number in 5 bytes or 9 bytes.
float 32 stores a floating point number in IEEE 754 single precision floating point number format:
+--------+--------+--------+--------+--------+
|  0xca  |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX
+--------+--------+--------+--------+--------+

float 64 stores a floating point number in IEEE 754 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 754 single precision floating point number
* YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY is a big-endian
  IEEE 754 double precision floating point number

 

小端法变大端法把自己顺序调整下就好了

在SimpleMsgPack中有一个这样的函数,可以对Double类型的数据进行交换字节数。

procedure swap64Ex(const v; out outVal);
begin
  // 7F F5 B8 6F B5 0E 04 40

  // 40 04 0E B5 6F B8 F5 7F
  PByte(@outVal)^ := PByte(IntPtr(@v) + 7)^;
  PByte(IntPtr(@outVal) + 1)^ := PByte(IntPtr(@v) + 6)^;
  PByte(IntPtr(@outVal) + 2)^ := PByte(IntPtr(@v) + 5)^;
  PByte(IntPtr(@outVal) + 3)^ := PByte(IntPtr(@v) + 4)^;
  PByte(IntPtr(@outVal) + 4)^ := PByte(IntPtr(@v) + 3)^;
  PByte(IntPtr(@outVal) + 5)^ := PByte(IntPtr(@v) + 2)^;
  PByte(IntPtr(@outVal) + 6)^ := PByte(IntPtr(@v) + 1)^;
  PByte(IntPtr(@outVal) + 7)^ := 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一样。

时间: 2024-10-08 15:58:18

关于SimpleMsgPack中swap引发的问题大端法和小端法研究笔记的相关文章

大端法和小端法

引言 在计算机内存中,通常是以字节(Byte),也就是 8 个位(Bit)为基本存储单元(也有以 16 位为基本存储单元的).对于跨越多个字节的数据类型(比如 int 长 4 个字节),如何在内存中对这些字节进行排序有两种常见的方法:大端法(Big-endian)和小端法(Little-endian) [注]首先不管是大端法还是小端法存储,计算机在内存中存放数据的顺序都是从低地址到高地址,所不同的是首先取低字节的数据存放在低地址还是取高字节数据存放在低地址. 基本概念 高位放在低地址就是大端法

网络通信之 字节序转换原理与网络字节序、大端和小端模式

原文地址:http://www.cnblogs.com/fuchongjundream/p/3914770.html 一.在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节.小端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要取高字节,真正取得是低

大端法、小端法、网络字节序 转

一般来说,大部分用户的操作系统(如windows, FreeBsd,Linux)是Little Endian 的.少部分,如MAC OS ,是Big Endian 的. 所谓MSB (Most Significant Byte)就是,一个数字中,最重要的那位, 比如,12004,中文读作,一万两千零四,那最高位的1,就表示了一万,此处就称作MSB,最有意义的位. 而LSB (Least Significant Byte)与MSB相反,个位数4就可以称为LSB, 在草稿纸上演算的时候,我们习惯左边

网络通信时字节序转换原理与网络字节序、大端和小端模式

引言:在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节.小端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要取高字节,真正取得是低字节),接收方网络协议函数接收时会将接收到的第一个字节存放到低地址(想要接收高字节,真正接收的是低字节),所以最后双

网络通信之字节序转换原理与网络字节序、大端和小端模式

一.在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节.小 端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要取高字节,真正取得是低字节),接收方网络 协议函数接收时会将接收到的第一个字节存放到低地址(想要接收高字节,真正接收的是低字节),所以最后

关于字节序(大端法、小端法)的定义

<UNXI网络编程>定义:术语“小端”和“大端”表示多字节值的哪一端(小端或大端)存储在该值的起始地址.小端存在起始地址,即是小端字节序:大端存在起始地址,即是大端字节序. 也可以说: 1.小端法(Little-Endian)就是低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端. 2.大端法(Big-Endian)就是高位字节排放在内存的低地址端即该值的起始地址,低位字节排放在内存的高地址端. 举个简单的例子,对于整形0x12345678.它在大端法和小端法的系统内中

变量在内存中的存储方式-----“大端”和“小端”

"大端"和"小端"可以追溯到1726年的Jonathan Swift的<格列佛游记>,其中一篇讲到有两个国家因为吃鸡蛋究竟是先打破较大的一端还是先打破较小的一端而争执不休,甚至爆发了战争.1981年10月,Danny Cohen的文章<论圣战以及对和平的祈祷>(On holy wars and a plea for peace)将这一对词语引入了计算机界(<程序设计实践>第9章).这么看来,所谓大端和小端,也就是big-endia

我如何确定一个机器的字节顺序是大端还是小端?

通常的技巧是使用一个指针: int x = 1; if(*(char *)&x == 1) printf("little-endian\n"); else printf("big-endian\n"); 或者一个union: union { int i; char c[sizeof(int)]; } x; x.i = 1; if(x.c[0] == 1) printf("little-endian\n"); else printf(&qu

大端和小端(big endian little endian)

一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放据的低位字节到高位字节). 例如,假设从内存地址 0x0000 开始有以下数据:  0x0000         0x0001       0x0002       0x0003  0x12            0x34