C++内存操作十六进制转浮点数

问题背景如下,在某些串口通信过程中会得到类似于下图所示的数据,数据格式为每四个十六进制数为一组,表示一个浮点数,在下图所示的数据中每一行包含三个浮点数,最后多出来一个用于校验。其中每个浮点数为左边低字节右边高字节。

 首先想说明的一点是,这个问题当然可以通过数学计算的方式解决。在计算机内存中,一个浮点数(float类型,32位)由四个字节表示,最高位表示符号,接下来8位表示阶码,然后23位表示尾数。例如上图中的第一个浮点数,按照从高位到低位的顺序写为BF 7D A0 C8,写成二进制形式为10111111 01111101 10100000 11001000;最高位为1,表示为负数;阶码部分为01111110,转换成十进制表示为126,去掉偏移量127,实际值为-1;尾数部分为1111101 10100000 11001000,根据指数部分为-1,浮点数实际数值的二进制表示为1.1111101 10100000 11001000\times 2^{^{-1}},即0.11111101 10100000 11001000,转换成十进制表示为0.99073457717895507813。具体关于浮点数的表示,以及相关的数制转换可以查阅相关的资料和博客。

然而,图中给出的数据格式与浮点数在内存中的表示是一致的,也就是说,如果将内存中的连续四个字节填充为上述的数据,例如BF 7D A0 C8,然后将这四个字节整体当作浮点数来读取,理应得到相应的结果0.99073457717895507813。然而此处需要特别注意的是数据类型在实际计算机中的表示方式,一定要是四个字节才行。在Visual C++中float类型是用四个字节来表示的,所以可以这样操作。下面列举两种具体操作方式。

1  通过指针进行转换

由于在C/C++中char类型是用一个字节表示的,所以用一个包含4个元素的char类型的数组,可以表示内存中的连续4个字节。将4个字节分别填充为对应的数据后,用一个float类型的指针来读取整体相应的内容。

unsigned char s[4];
float *p;
float num;
s[0]=0xC8;
s[1]=0xA0;
s[2]=0x7D;
s[3]=0xBF;
p=(float*)s;
num=*p;
cout <<"num = "<< num << endl;

将变量num的值输出结果如下图,可以得到正确的结果。

 2  位域

位域(Bit Field)是一种比较稍微特殊一点的方式,可以对一个变量的各个位进行操作,但是需要特别注意位域的分配方式,因为位域在内存中的对齐方式不一定如我们所想的那样,关于位域的具体介绍可以参考维基百科和Microsoft的文档,在对一些DSP进行编程时经常会用到位域的方式,如TI的TMS320F2812的代码框架就对DSP的各个寄存器定义了很多位域。由于此处正好是将一个浮点数划分为4个字节,而字节在内存中可以很方便地对齐,所以使用位域的方式来处理也是可以的。

具体的实现方式是采用struct类型定义位域,然后采用union类型和一个变量进行绑定。

typedef unsigned int Bit; //位域的类型必须是整型或枚举整型,通常用无符号整型
struct BitField  //采用结构体来划分位域,每个位域后面用冒号和数字表示位域所占的位数,
{                //此处定义了F1,F2,F3,F4四个位域,所有位域均占8位,一共32位。
  Bit F1:8;
  Bit F2:8;
  Bit F3:8;
  Bit F4:8;
};
union BitFieldForFloat  //采用联合体来将位域和float变量进行绑定,
{                       //因为union类型的各个成员共用同一块内存区域。
  struct BitField bitfield;
  float value;
};

定义好了位域之后,就可以采用位域来进行数据的转换了。 

union BitFieldForFloat num;
num.value=0;
num.bitfield.F1=0xC8;
num.bitfield.F2=0xA0;
num.bitfield.F3=0x7D;
num.bitfield.F4=0xBF;
cout<<"the value of the float number is "<<num.value<<endl;

程序输出结果如下图,可以得到正确的结果。 

最后说明一下,其实位域更多的是用来对一个字节内的各个部分进行操作的,比如可以将一个字节(共8位)划分为3,3,2三个部分,然后对一个char类型的变量进操作,如下所示。当然,位域的划分也可以跨越多个字节。

typedef unsigned int Bit;
struct BitField
{
  Bit bit_0_to_2:3;
  Bit bit_3_to_5:3;
  Bit bit_6_to_7:2;
}
union BitFieldForChar
{
  struct BitField bitfield;
  char value;
}
union BitFieldForChar number;

参考链接

关于浮点数表示的一个博客

16进制转浮点数的一个在线计算器​​​​​​​

Microsoft关于位域的文档

维基百科中位域的文档

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在LabVIEW中,将十六进制换为浮点数可以通过使用Hexadecimal String to Number函数来实现。以下是一个将十六进制字符串换为浮点数的简单例子。 1. 首先,在Block Diagram中创建一个新的VI。 2. 在Front Panel上创建一个String控件,用于输入十六进制字符串。 3. 在Block Diagram中,在String控件下方添加一个Hexadecimal String to Number函数。这个函数将把输入的十六进制字符串换为浮点数。 4. 通过右键单击Hexadecimal String to Number函数的输入端,选择Create»Constant,创建一个常量值,用于指定浮点数的类型(单精度或双精度)。你可以选择Single或Double。将此常量连接到Hexadecimal String to Number函数的数据类型输入端。 5. 将String控件的输出连接到Hexadecimal String to Number函数的输入端。 6. 从Hexadecimal String to Number函数的输出终端连接一个Numeric Indicator,用于显示换后的浮点数。 7. 运行VI,并在String控件中输入一个十六进制字符串,然后观察Numeric Indicator中显示的浮点数。 通过这些步骤,你就可以将十六进制字符串换为浮点数。这在处理数据换和显示方面非常有用,尤其在与外部设备进行通信或处理二进制数据时。 ### 回答2: 在LabVIEW中,将十六进制换为浮点数可以通过以下步骤来实现: 1. 首先,将十六进制换为十进制数。可以使用Hexadecimal String To Number函数将十六进制字符串换为十进制数值。 2. 然后,使用Hexadecimal And Variant Data Type函数将十进制数值换为Variant数据类型。 3. 接下来,使用Variant To Data函数将Variant数据类型换为单精度浮点数。 4. 最后,可以将换后的浮点数输出到需要的地方进行进一步处理或显示。 以下是一个示例程序,展示了如何在LabVIEW中实现十六进制浮点数: 1. 使用"Hexadecimal String To Number"函数将十六进制字符串换为十进制数值。 2. 使用"Hexadecimal And Variant Data Type"函数将十进制数值换为Variant数据类型。 3. 使用"Variant To Data"函数将Variant数据类型换为浮点数。 4. 将换后的浮点数输出到需要的地方进行进一步处理或显示。 请注意,以上仅为一种实现方式,您可以根据需要进行适当的调整和改进。 ### 回答3: 在LabVIEW中,将十六进制换为浮点数可以使用内置的十六进制换函数。下面是一个简单的示例: 首先,通过使用十六进制数作为输入,你可以将其传递给"String To Byte Array"函数,将十六进制字符串换为字节数组。这样可以将十六进制数的每个字节拆分出来。 接下来,将字节数组传递给"Join Numbers"函数,用于将字节重新组合为一个32位整数。 然后,使用"32-bit Integer To Single Precision Floating Point"函数将整数换为单精度浮点数。 最后,你可以将结果输出为浮点数。 通过这种方式,你可以将十六进制换为浮点数。 请注意,对于十六进制数的输入,你可能需要确保输入的格式正确,例如,包含正确的前缀和位数。此外,你可能需要处理一些特殊情况,例如处理负数和非正常化的浮点数。 总之,LabVIEW提供了一系列内置函数,可以用于将十六进制换为浮点数,你可以根据自己的需求选择合适的函数组合来实现这个换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值