打印

嵌入式中浮点型数据转换为字节类型的方法

[复制链接]
3243|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qbwww|  楼主 | 2021-7-7 21:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
什么是浮点数
浮点数是指一种既包含小数又包含整数的数据类型。
浮点型变量分类
浮点型分为单精度(float型)和双精度(double型)。浮点型变量使用定义。如下:
  • float a; // 声明单精度浮点型变量
  • double b; // 声明双精度浮点型变量


单精度(float型)与双精度(double型)的区别
float 单精度浮点数内存中占 4 个字节,用 32 位二进制描述。
double 双精度浮点数内存中占 8个字节,用 64 位二进制描述。
Float 有效数字6-7位,数值范围:-3.4*10(-38)~3.4*10(38)。
Double 有效数字15-16位,数值范围:-1.7*10(-308)~1.7*10(308)。
简单来说就是Float类型可以保存的数据最多为小数点后6位小数。比如说保存3.1415926这个数据只能保存下来的是3.141593。double类型也是如此最多可以保存小数点后15位小数。
float 优点:省内存,运算速度快。
float 缺点:精度低。
double 优点:精度高。
double 缺点:占内存,运算速度慢。
在嵌入式编程的时候一般都是以省内存,加快运算速度优先。所以在选择使用浮点型时float就可以满足大部分需求,当需要高精度的时候必须使用double进行运算。
浮点型数据在嵌入式中的使用
在嵌入式数据通讯过程中一般是以字节的形式进行数据交互。要想传输一个浮点数需要把浮点数转换为字节的形式。
MCU不能直接保存浮点型数据,能直接保存的是0或1。把数据保存到MCU中比较常用的保存方法就是以字节的方式把数据写到MCU的存储模块中去。所以说要保存一个浮点型数据到MCU前需要先把浮点型数据转换成字节的形式。下面就来说一说浮点型转换为字节类型的一些方法:
方法一
强制转换,就是把浮点型数据直接赋值到整型的方法,例子如下:
  • unsigned char a;
  • float b=3.14;
  • a=(unsigned char)b; //直接赋值有时候编译会报错所以需要在前面加强制转换(unsigned char)。


你觉得现在a等于多少?运行结果a=3。强制转换的缺点就是直接把小数位忽略掉保留整数。
要想把小数保留下来可以先把b乘以100,b=314再强制转换到a,这时a=314,再把a除以100赋值到浮点类型还原到原来的浮点数。强制转换到a后a=314吗?答案是a!=314。为什么?因为unsigned char是一个字节即(1111 1111)八位。值得范围为0~255,314>255赋值无效。正确的需要大a的定位类型改为数组使用两个字节保存以方便写入芯片,更改为:
  • unsigned char a[2]; //定义2个元素的数组,代表高位和低位
  • float b=3.14;
  • unsigned short int c=(unsigned short int)b*100; //3.14乘以100后强制转换到c,(unsigned short int)表示16位的无符号整型。通常为uint16_t这样写法。
  • a[0]=c>>8; //或者a[0]=c/256。>>8,相当于c除以256取整,所以a[0]=1;
  • a[1]=c; //c=314,赋值到a[1]中因为a[1]为unsigned char类型最大为255,所以当值大于255就会从零开始,所以a[1]最终等于58。类似于十进制的个位十位。还原数据就是一个相反的过程就是a[0]*256+a[1]或者a[0]<<8+a[1]。




方法二
使用打印函数转换为字符串存到字节数组。实例如下:
  • char pdata[10];
  • float b=3.14;
  • sprintf(pdata,"%.2f",b); //打印到文件函数,就是把浮点型b打印到pdata字节数组。
  • /*
  • 以16进制的形式打印pdata的元素,3.14变成了33 2e 31 34,其实就是3.14本来是数字的变成了字符,然后以ascll码表对应的十六进制值保存到字节数组中来。
  • 把字符串转换为浮点型数据的方法可以使用C库函数atof()进行转换。使用方法;
  • */
  • #include <stdlib.h>
  • char ch[]="3.14";
  • float fa=atof(str);



方法三
基于IEEE754格式的浮点数据方法,这是一种标准的浮点格式方法。单精度浮点型以4字节保存,双精度以8字节保存。转换相关方法如下。
单精度浮点数(float)
  • //浮点数转字节数组
  • void floatbytes(float data, unsigned char bytes[])
  • {
  •     unsigned char i;
  •     char* p = (char*)&data; //将float类型的指针强制转换为unsigned char型
  •       for(i=0; i<4; i++)
  •       {
  •       bytes = *p++; //将相应地址中的数据保存到unsigned char数组中
  •       }
  • }
  • //字节数组转浮点数
  • float bytesfloat(unsigned char bytes[])
  • {
  •   float data = *((float *)bytes); //直接将unsigned char型的指针强制转换为double类型
  •   return data;
  • }


双精度浮点数(double )
  • //浮点型double转字节数组
  • void double2bytes(double data, unsigned char bytes[])
  • {
  •   int i;
  •   char* p = (char*)&data; //将double类型的指针强制转换为unsigned char型
  •     for(i=0; i<8; i++)
  •     {
  •     bytes = *p++; //将相应地址中的数据保存到unsigned char数组中
  •     }
  • }
  • //字节数组转双精度浮点型数据double(小端模式)
  • double bytes2double(unsigned char bytes[])
  • {
  •       double data = *((double *)bytes); //直接将unsigned char型的指针强制转换为double类型
  •       return data;
  • }


有空可以验证一下这种方式的转换。以单精度为例使用方法如下:
  • float a=3.14;
  • unsigned char fch[4];
  • Floatbytes(a,fch);


你还知道其他的相关转换方法吗?欢迎留言。
每一种方法都有其优点和缺点,上面所说到的三种方法方法一相对来说比较容易理解和使用也不需要占用很多个字节,但是不太灵活。方法二转换成数组比较简单但是占用多少个字节不定,小数位保存越多占用字节越多,多个数据一起的时候稍微会麻烦一点。方法三,标准的保存方式,理解起来比较复杂一点。但是能够很好地把浮点数保存下来也无需处理符号位。对于比C语言更复杂一点的编程语言都有现有的转换函数调用。
到底那种方法好这就需要自己去验证了。

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

733

主题

4517

帖子

14

粉丝