有关字节型转换为浮点型

背景:由于先前正在用Qt做上位机实现从STM32中发送字节,从而在Qt上位机上接收并转换为浮点型来进行保存。查阅了很多资料想了很多的解决方案。

有关浮点数在内存中的表示:

        浮点型数据在存储方式上遵从IEEE规范。符号位、指数位、尾数部分三部分组成

        说明:

        1.有效数据位最高位必须为1,因为只能为1,所以不必存储,而剩下的所有位称为尾数部分,是需要存储在内存中的数据

       2.R32.24和R64.53的存储方式都是用科学计数法来存储数据的。

float的存储方式:

        float单精度浮点型遵从IEEER32.24(即32位形式存储,4字节,有效数据位为24位)

31 30    23 22                    0
S  EEEEEEEE DDDDDDDDDDDDDDDDDDDDDDD

float转换为内存的步骤:

        1>先将实数绝对值转换为对应二进制格式

        2>将二进制格式实数小数点向左或右移n位,直到小数点移动到第高位的“1”右边

        3>从小数点右边第一位开始数出23位数字放入第22到第0位(实现尾数部分存储)

        4>根据原实数的正负,给符号位,即最高位的第31位赋值,为正则“0”,为负则“1”

        5>根据小数点移动方向判断指数正负,给指数位最高位(第30位赋值),左移为正,第30位放"1",右移或没移为负,放入"0"

        6>如果为左移得到:(n-1)的值化为二进制,并在左边加"0"补足7位,放入第29到第23位.

            如果为右移或没移动(n=0):n化为二进制在左边加"0"补足7位,再各位取反,再放入第29到23位

例:12.5转换为字节:

        (1)12.5实数绝对值转换为二进制为1100.1

        (2)向左移动3位,转换为科学计数法1.1001E3,n=3

        (3)将小数点右边第一位开始输出23位放入到第22位到第0位,数据为D存储形式:

  DDDDDDDDDDDDDDDDDDDDDDD
  10010000000000000000000

        (4)12.5为正数,最高位,即第31位置"0",S=0

        (5)n左移得到尾数部分,指数为正,第30位置"1"

        (6)n-1=2=0010,向左加"0"补足7位,放入第29到第23位

所以,指数位E为:

 EEEEEEEE
 10000010
31 30    23   22                    0
S  EEEEEEEE   DDDDDDDDDDDDDDDDDDDDDDD
0  10000010   10010000000000000000000

存储字节数据转换为float步骤:

将一个内存存储的float二进制格式转换为十进制步骤:

        (1)将第22到第0位的二进制数写出来,在最左边补一位"1",得到二十四位有效数组.将小数点在最左边那个"1"的右边

        (2)取出第29到第第23位所表示的值n.当30位是"0",将各位取反.当30位是1"时n增加1

        (3)当第30位是"0时,将小数点左移n位;当第30位是"1"时,右移n位,得到一个二进制表示的实数

        (4)将这个二进制实数化为十进制,并根据第31位是"0"还是"1"加上正负号即可.

同样以12.5的二进制为例:

        (1)在最左边补"1",得到二十四位有效数字。将小数点点在最左边的“1””右边

 1.10010000000000000000000

        (2) 取出第29到第23位所表示的值n。由于30位是“1”,所有将n增1为0000011(即n=3)
        (3) 由于30位是“1”,将小数点右移3位,得到二进制实数为:​​​​​​​​​​​​​​

1100. 10000000000000000000

        ​​​​​​​(4) 转换为十进制数,由于31位为“0”,所有结果为12.5​​​​​​​​​​​​​​​​​​​​​

double的存储方式:(与float原理同)

double双精度浮点型遵从IEEER64.53(即64位形式存储,8字节,有效数据位为53位)

 


        言归正传,在搞明白了浮点型的存储形式之后,单片机将浮点数转换为字节发送给上位机,上位机接收后可以根据十六进制数据显示其存储形式。虽然了解了二进制如何转变取回浮点型的步骤。但是,难道我还要专门写一个算法来进行取位、判断、计算操作来转换吗,显然我觉得一定有什么办法可以实现更简单的转换。

        基于计算机内部对数据类型的解码,我突然想到是不是只要定义一个浮点型的变量,将内存形式放入其中,再去调用和使用这个变量,是不是就会输出的是内存形式对应解码的那个浮点型呢?经测试,内存拷贝无疑就是最好的方法!

内存拷贝函数memcpy

memcpy

原型:extern void *memcpy (void *dest,void *src, unsigned int count);

功能: 由src所指内存区域复制count个字节到dest所指内存区域

说明:sec和dest所指内存区域不能重叠,函数返回指向dest的指针。

作用:用来做内存拷贝,可以拿它拷贝任何数据类型的对象,可以指定拷贝数据长度

    QByteArray buffer;    
    float map_x=0;

    QByteArray x = buffer.mid(1,4);
    memcpy(&map_x, x.data(), 4);

与memcpy类似的其他函数拓展

strcpy

原型:extern char*strcpy(char* dest ,char*src)

功能:把src所指由NULL结束的字符串复制到dest所指的数组中。

说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串,f返回指向 dest的指针

作用:只能拷贝字符串,遇到'/0'就结束拷贝

memset

原型:extern void * memset(void *buffer, int c , int count)

buffer: 指针或数组c,赋给buffer的值,count:buffer的长度

作用:将已开辟内存空间buffer的首count个字节的值设为值c;

          常用于内存空间初始化:

          方便清空结构类型的变量或数据

总结:

memset主要应用是初始化某个内存空间。

memcpy是用于copy源空间的数据到目的空间中。

strcpy用于字符串copy,遇到‘/0’,将结束。

参考资料:

(30条消息) 浮点数与字节数据转换详解_wsqyouth的博客-CSDN博客_字节转浮点数

:内含浮点型和字节数据的转换例子细节,本文大多内容由本文总结

n​​​​​​​​​​​​​​浮点型数据(float, double)存储IEEE标准解析和应用 - zhugehq - 博客园 (cnblogs.com)

:内含对浮点型数据存储形式中数值的存放对E指数位的值有另一种解释:“E位的编码形式并非常用的补码形式(正数是它本身,负数符号位变1数据取反加一),而是把E位的8位能代表的数据空间(0-255)左右分为两半,以127为中点,代表0。如果指数为是1,则E位是128;如果指数位是2,则E位是129;如果指数位是-1,则E位是126,以此类推。”

浮点数在计算机中存储方式 - Robin Zhang - 博客园 (cnblogs.com)

:说明浮点型转换过程中可能会出现的误差和原因分析

(31条消息) Qt总结之二十三:QByteArray与char、int、float(及其数组)之间的互相转化_ooMelloo的博客-CSDN博客_qbytearray转qint64

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值